Home | History | Annotate | Line # | Download | only in raidframe
rf_disks.c revision 1.6
      1  1.6  oster /*	$NetBSD: rf_disks.c,v 1.6 1999/02/24 00:00:03 oster Exp $	*/
      2  1.6  oster /*-
      3  1.6  oster  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      4  1.6  oster  * All rights reserved.
      5  1.6  oster  *
      6  1.6  oster  * This code is derived from software contributed to The NetBSD Foundation
      7  1.6  oster  * by Greg Oster
      8  1.6  oster  *
      9  1.6  oster  * Redistribution and use in source and binary forms, with or without
     10  1.6  oster  * modification, are permitted provided that the following conditions
     11  1.6  oster  * are met:
     12  1.6  oster  * 1. Redistributions of source code must retain the above copyright
     13  1.6  oster  *    notice, this list of conditions and the following disclaimer.
     14  1.6  oster  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.6  oster  *    notice, this list of conditions and the following disclaimer in the
     16  1.6  oster  *    documentation and/or other materials provided with the distribution.
     17  1.6  oster  * 3. All advertising materials mentioning features or use of this software
     18  1.6  oster  *    must display the following acknowledgement:
     19  1.6  oster  *        This product includes software developed by the NetBSD
     20  1.6  oster  *        Foundation, Inc. and its contributors.
     21  1.6  oster  * 4. Neither the name of The NetBSD Foundation nor the names of its
     22  1.6  oster  *    contributors may be used to endorse or promote products derived
     23  1.6  oster  *    from this software without specific prior written permission.
     24  1.6  oster  *
     25  1.6  oster  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     26  1.6  oster  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  1.6  oster  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  1.6  oster  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     29  1.6  oster  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  1.6  oster  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  1.6  oster  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  1.6  oster  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  1.6  oster  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  1.6  oster  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  1.6  oster  * POSSIBILITY OF SUCH DAMAGE.
     36  1.6  oster  */
     37  1.6  oster 
     38  1.1  oster /*
     39  1.1  oster  * Copyright (c) 1995 Carnegie-Mellon University.
     40  1.1  oster  * All rights reserved.
     41  1.1  oster  *
     42  1.1  oster  * Author: Mark Holland
     43  1.1  oster  *
     44  1.1  oster  * Permission to use, copy, modify and distribute this software and
     45  1.1  oster  * its documentation is hereby granted, provided that both the copyright
     46  1.1  oster  * notice and this permission notice appear in all copies of the
     47  1.1  oster  * software, derivative works or modified versions, and any portions
     48  1.1  oster  * thereof, and that both notices appear in supporting documentation.
     49  1.1  oster  *
     50  1.1  oster  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     51  1.1  oster  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     52  1.1  oster  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     53  1.1  oster  *
     54  1.1  oster  * Carnegie Mellon requests users of this software to return to
     55  1.1  oster  *
     56  1.1  oster  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     57  1.1  oster  *  School of Computer Science
     58  1.1  oster  *  Carnegie Mellon University
     59  1.1  oster  *  Pittsburgh PA 15213-3890
     60  1.1  oster  *
     61  1.1  oster  * any improvements or extensions that they make and grant Carnegie the
     62  1.1  oster  * rights to redistribute these changes.
     63  1.1  oster  */
     64  1.1  oster 
     65  1.1  oster /***************************************************************
     66  1.1  oster  * rf_disks.c -- code to perform operations on the actual disks
     67  1.1  oster  ***************************************************************/
     68  1.1  oster 
     69  1.1  oster #include "rf_types.h"
     70  1.1  oster #include "rf_raid.h"
     71  1.1  oster #include "rf_alloclist.h"
     72  1.1  oster #include "rf_utils.h"
     73  1.1  oster #include "rf_configure.h"
     74  1.1  oster #include "rf_general.h"
     75  1.1  oster #include "rf_options.h"
     76  1.1  oster #include "rf_sys.h"
     77  1.1  oster 
     78  1.1  oster #include <sys/types.h>
     79  1.1  oster #include <sys/param.h>
     80  1.1  oster #include <sys/systm.h>
     81  1.1  oster #include <sys/proc.h>
     82  1.1  oster #include <sys/ioctl.h>
     83  1.1  oster #include <sys/fcntl.h>
     84  1.1  oster #include <sys/vnode.h>
     85  1.1  oster 
     86  1.6  oster /* XXX these should be in a header file somewhere */
     87  1.5  oster int raidlookup __P((char *, struct proc * p, struct vnode **));
     88  1.6  oster int raidwrite_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
     89  1.6  oster int raidread_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
     90  1.6  oster void rf_UnconfigureVnodes( RF_Raid_t * );
     91  1.6  oster int rf_CheckLabels( RF_Raid_t *, RF_Config_t *);
     92  1.1  oster 
     93  1.1  oster #define DPRINTF6(a,b,c,d,e,f) if (rf_diskDebug) printf(a,b,c,d,e,f)
     94  1.1  oster #define DPRINTF7(a,b,c,d,e,f,g) if (rf_diskDebug) printf(a,b,c,d,e,f,g)
     95  1.1  oster 
     96  1.6  oster /**************************************************************************
     97  1.1  oster  *
     98  1.1  oster  * initialize the disks comprising the array
     99  1.1  oster  *
    100  1.6  oster  * We want the spare disks to have regular row,col numbers so that we can
    101  1.6  oster  * easily substitue a spare for a failed disk.  But, the driver code assumes
    102  1.6  oster  * throughout that the array contains numRow by numCol _non-spare_ disks, so
    103  1.6  oster  * it's not clear how to fit in the spares.  This is an unfortunate holdover
    104  1.6  oster  * from raidSim.  The quick and dirty fix is to make row zero bigger than the
    105  1.6  oster  * rest, and put all the spares in it.  This probably needs to get changed
    106  1.6  oster  * eventually.
    107  1.1  oster  *
    108  1.6  oster  **************************************************************************/
    109  1.6  oster 
    110  1.5  oster int
    111  1.6  oster rf_ConfigureDisks( listp, raidPtr, cfgPtr )
    112  1.6  oster 	RF_ShutdownList_t **listp;
    113  1.6  oster 	RF_Raid_t *raidPtr;
    114  1.6  oster 	RF_Config_t *cfgPtr;
    115  1.1  oster {
    116  1.5  oster 	RF_RaidDisk_t **disks;
    117  1.5  oster 	RF_SectorCount_t min_numblks = (RF_SectorCount_t) 0x7FFFFFFFFFFFLL;
    118  1.5  oster 	RF_RowCol_t r, c;
    119  1.6  oster 	int bs, ret;
    120  1.5  oster 	unsigned i, count, foundone = 0, numFailuresThisRow;
    121  1.6  oster 	int num_rows_done, num_cols_done;
    122  1.5  oster 
    123  1.5  oster 	num_rows_done = 0;
    124  1.5  oster 	num_cols_done = 0;
    125  1.5  oster 
    126  1.6  oster 	RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *),
    127  1.6  oster 			(RF_RaidDisk_t **), raidPtr->cleanupList);
    128  1.5  oster 	if (disks == NULL) {
    129  1.5  oster 		ret = ENOMEM;
    130  1.5  oster 		goto fail;
    131  1.5  oster 	}
    132  1.5  oster 	raidPtr->Disks = disks;
    133  1.5  oster 
    134  1.5  oster 	/* get space for the device-specific stuff... */
    135  1.5  oster 	RF_CallocAndAdd(raidPtr->raid_cinfo, raidPtr->numRow,
    136  1.5  oster 	    sizeof(struct raidcinfo *), (struct raidcinfo **),
    137  1.5  oster 	    raidPtr->cleanupList);
    138  1.5  oster 	if (raidPtr->raid_cinfo == NULL) {
    139  1.5  oster 		ret = ENOMEM;
    140  1.5  oster 		goto fail;
    141  1.5  oster 	}
    142  1.5  oster 	for (r = 0; r < raidPtr->numRow; r++) {
    143  1.5  oster 		numFailuresThisRow = 0;
    144  1.6  oster 		/* We allocate RF_MAXSPARE on the first row so that we
    145  1.6  oster 		   have room to do hot-swapping of spares */
    146  1.6  oster 		RF_CallocAndAdd(disks[r], raidPtr->numCol
    147  1.6  oster 				+ ((r == 0) ? RF_MAXSPARE : 0),
    148  1.6  oster 				sizeof(RF_RaidDisk_t), (RF_RaidDisk_t *),
    149  1.6  oster 				raidPtr->cleanupList);
    150  1.5  oster 		if (disks[r] == NULL) {
    151  1.5  oster 			ret = ENOMEM;
    152  1.5  oster 			goto fail;
    153  1.5  oster 		}
    154  1.5  oster 		/* get more space for device specific stuff.. */
    155  1.5  oster 		RF_CallocAndAdd(raidPtr->raid_cinfo[r],
    156  1.5  oster 		    raidPtr->numCol + ((r == 0) ? raidPtr->numSpare : 0),
    157  1.5  oster 		    sizeof(struct raidcinfo), (struct raidcinfo *),
    158  1.1  oster 		    raidPtr->cleanupList);
    159  1.5  oster 		if (raidPtr->raid_cinfo[r] == NULL) {
    160  1.5  oster 			ret = ENOMEM;
    161  1.5  oster 			goto fail;
    162  1.5  oster 		}
    163  1.5  oster 		for (c = 0; c < raidPtr->numCol; c++) {
    164  1.6  oster 			ret = rf_ConfigureDisk(raidPtr,
    165  1.6  oster 					       &cfgPtr->devnames[r][c][0],
    166  1.6  oster 					       &disks[r][c], r, c);
    167  1.5  oster 			if (ret)
    168  1.5  oster 				goto fail;
    169  1.6  oster #ifdef NOT_YET_BOYS_AND_GIRLS
    170  1.6  oster 			if (disks[r][c].status == rf_ds_optimal) {
    171  1.6  oster 				raidread_component_label(
    172  1.6  oster 					 raidPtr->raid_cinfo[r][c].ci_dev,
    173  1.6  oster 					 raidPtr->raid_cinfo[r][c].ci_vp,
    174  1.6  oster 					 &raidPtr->raid_cinfo[r][c].ci_label);
    175  1.6  oster 			}
    176  1.6  oster #endif
    177  1.5  oster 			if (disks[r][c].status != rf_ds_optimal) {
    178  1.5  oster 				numFailuresThisRow++;
    179  1.5  oster 			} else {
    180  1.5  oster 				if (disks[r][c].numBlocks < min_numblks)
    181  1.5  oster 					min_numblks = disks[r][c].numBlocks;
    182  1.5  oster 				DPRINTF7("Disk at row %d col %d: dev %s numBlocks %ld blockSize %d (%ld MB)\n",
    183  1.5  oster 				    r, c, disks[r][c].devname,
    184  1.5  oster 				    (long int) disks[r][c].numBlocks,
    185  1.5  oster 				    disks[r][c].blockSize,
    186  1.6  oster 				    (long int) disks[r][c].numBlocks *
    187  1.6  oster 					 disks[r][c].blockSize / 1024 / 1024);
    188  1.5  oster 			}
    189  1.5  oster 			num_cols_done++;
    190  1.5  oster 		}
    191  1.5  oster 		/* XXX fix for n-fault tolerant */
    192  1.6  oster 		/* XXX this should probably check to see how many failures
    193  1.6  oster 		   we can handle for this configuration! */
    194  1.5  oster 		if (numFailuresThisRow > 0)
    195  1.5  oster 			raidPtr->status[r] = rf_rs_degraded;
    196  1.5  oster 		num_rows_done++;
    197  1.5  oster 	}
    198  1.6  oster 
    199  1.5  oster 	/* all disks must be the same size & have the same block size, bs must
    200  1.5  oster 	 * be a power of 2 */
    201  1.5  oster 	bs = 0;
    202  1.5  oster 	for (foundone = r = 0; !foundone && r < raidPtr->numRow; r++) {
    203  1.5  oster 		for (c = 0; !foundone && c < raidPtr->numCol; c++) {
    204  1.5  oster 			if (disks[r][c].status == rf_ds_optimal) {
    205  1.5  oster 				bs = disks[r][c].blockSize;
    206  1.5  oster 				foundone = 1;
    207  1.5  oster 			}
    208  1.5  oster 		}
    209  1.5  oster 	}
    210  1.5  oster 	if (!foundone) {
    211  1.5  oster 		RF_ERRORMSG("RAIDFRAME: Did not find any live disks in the array.\n");
    212  1.5  oster 		ret = EINVAL;
    213  1.5  oster 		goto fail;
    214  1.5  oster 	}
    215  1.5  oster 	for (count = 0, i = 1; i; i <<= 1)
    216  1.5  oster 		if (bs & i)
    217  1.5  oster 			count++;
    218  1.5  oster 	if (count != 1) {
    219  1.5  oster 		RF_ERRORMSG1("Error: block size on disks (%d) must be a power of 2\n", bs);
    220  1.5  oster 		ret = EINVAL;
    221  1.5  oster 		goto fail;
    222  1.5  oster 	}
    223  1.6  oster 
    224  1.6  oster #if NOT_YET_BOYS_AND_GIRLS
    225  1.6  oster 	if (rf_CheckLabels( raidPtr, cfgPtr )) {
    226  1.6  oster 		printf("There were fatal errors (ignored for now)\n");
    227  1.6  oster 	}
    228  1.6  oster #endif
    229  1.5  oster 	for (r = 0; r < raidPtr->numRow; r++) {
    230  1.5  oster 		for (c = 0; c < raidPtr->numCol; c++) {
    231  1.5  oster 			if (disks[r][c].status == rf_ds_optimal) {
    232  1.5  oster 				if (disks[r][c].blockSize != bs) {
    233  1.5  oster 					RF_ERRORMSG2("Error: block size of disk at r %d c %d different from disk at r 0 c 0\n", r, c);
    234  1.5  oster 					ret = EINVAL;
    235  1.5  oster 					goto fail;
    236  1.5  oster 				}
    237  1.5  oster 				if (disks[r][c].numBlocks != min_numblks) {
    238  1.5  oster 					RF_ERRORMSG3("WARNING: truncating disk at r %d c %d to %d blocks\n",
    239  1.5  oster 					    r, c, (int) min_numblks);
    240  1.5  oster 					disks[r][c].numBlocks = min_numblks;
    241  1.5  oster 				}
    242  1.5  oster 			}
    243  1.5  oster 		}
    244  1.5  oster 	}
    245  1.5  oster 
    246  1.5  oster 	raidPtr->sectorsPerDisk = min_numblks;
    247  1.5  oster 	raidPtr->logBytesPerSector = ffs(bs) - 1;
    248  1.5  oster 	raidPtr->bytesPerSector = bs;
    249  1.5  oster 	raidPtr->sectorMask = bs - 1;
    250  1.5  oster 	return (0);
    251  1.1  oster 
    252  1.1  oster fail:
    253  1.6  oster 
    254  1.6  oster 	rf_UnconfigureVnodes( raidPtr );
    255  1.1  oster 
    256  1.5  oster 	return (ret);
    257  1.1  oster }
    258  1.1  oster 
    259  1.1  oster 
    260  1.6  oster /****************************************************************************
    261  1.1  oster  * set up the data structures describing the spare disks in the array
    262  1.1  oster  * recall from the above comment that the spare disk descriptors are stored
    263  1.1  oster  * in row zero, which is specially expanded to hold them.
    264  1.6  oster  ****************************************************************************/
    265  1.5  oster int
    266  1.6  oster rf_ConfigureSpareDisks( listp, raidPtr, cfgPtr )
    267  1.6  oster 	RF_ShutdownList_t ** listp;
    268  1.6  oster 	RF_Raid_t * raidPtr;
    269  1.6  oster 	RF_Config_t * cfgPtr;
    270  1.1  oster {
    271  1.6  oster 	int     i, ret;
    272  1.6  oster 	unsigned int bs;
    273  1.5  oster 	RF_RaidDisk_t *disks;
    274  1.5  oster 	int     num_spares_done;
    275  1.1  oster 
    276  1.5  oster 	num_spares_done = 0;
    277  1.5  oster 
    278  1.5  oster 	/* The space for the spares should have already been allocated by
    279  1.5  oster 	 * ConfigureDisks() */
    280  1.5  oster 
    281  1.5  oster 	disks = &raidPtr->Disks[0][raidPtr->numCol];
    282  1.5  oster 	for (i = 0; i < raidPtr->numSpare; i++) {
    283  1.5  oster 		ret = rf_ConfigureDisk(raidPtr, &cfgPtr->spare_names[i][0],
    284  1.6  oster 				       &disks[i], 0, raidPtr->numCol + i);
    285  1.5  oster 		if (ret)
    286  1.5  oster 			goto fail;
    287  1.5  oster 		if (disks[i].status != rf_ds_optimal) {
    288  1.6  oster 			RF_ERRORMSG1("Warning: spare disk %s failed TUR\n",
    289  1.6  oster 				     &cfgPtr->spare_names[i][0]);
    290  1.5  oster 		} else {
    291  1.5  oster 			disks[i].status = rf_ds_spare;	/* change status to
    292  1.5  oster 							 * spare */
    293  1.5  oster 			DPRINTF6("Spare Disk %d: dev %s numBlocks %ld blockSize %d (%ld MB)\n", i,
    294  1.5  oster 			    disks[i].devname,
    295  1.5  oster 			    (long int) disks[i].numBlocks, disks[i].blockSize,
    296  1.6  oster 			    (long int) disks[i].numBlocks *
    297  1.6  oster 				 disks[i].blockSize / 1024 / 1024);
    298  1.5  oster 		}
    299  1.5  oster 		num_spares_done++;
    300  1.5  oster 	}
    301  1.1  oster 
    302  1.5  oster 	/* check sizes and block sizes on spare disks */
    303  1.5  oster 	bs = 1 << raidPtr->logBytesPerSector;
    304  1.5  oster 	for (i = 0; i < raidPtr->numSpare; i++) {
    305  1.5  oster 		if (disks[i].blockSize != bs) {
    306  1.5  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);
    307  1.5  oster 			ret = EINVAL;
    308  1.5  oster 			goto fail;
    309  1.5  oster 		}
    310  1.5  oster 		if (disks[i].numBlocks < raidPtr->sectorsPerDisk) {
    311  1.5  oster 			RF_ERRORMSG3("Spare disk %s (%d blocks) is too small to serve as a spare (need %ld blocks)\n",
    312  1.6  oster 				     disks[i].devname, disks[i].blockSize,
    313  1.6  oster 				     (long int) raidPtr->sectorsPerDisk);
    314  1.5  oster 			ret = EINVAL;
    315  1.5  oster 			goto fail;
    316  1.5  oster 		} else
    317  1.5  oster 			if (disks[i].numBlocks > raidPtr->sectorsPerDisk) {
    318  1.5  oster 				RF_ERRORMSG2("Warning: truncating spare disk %s to %ld blocks\n", disks[i].devname, (long int) raidPtr->sectorsPerDisk);
    319  1.5  oster 
    320  1.5  oster 				disks[i].numBlocks = raidPtr->sectorsPerDisk;
    321  1.5  oster 			}
    322  1.5  oster 	}
    323  1.5  oster 
    324  1.5  oster 	return (0);
    325  1.1  oster 
    326  1.1  oster fail:
    327  1.2  oster 
    328  1.5  oster 	/* Release the hold on the main components.  We've failed to allocate
    329  1.6  oster 	 * a spare, and since we're failing, we need to free things..
    330  1.6  oster 
    331  1.6  oster 	 XXX failing to allocate a spare is *not* that big of a deal...
    332  1.6  oster 	 We *can* survive without it, if need be, esp. if we get hot
    333  1.6  oster 	 adding working.
    334  1.1  oster 
    335  1.6  oster 	 If we don't fail out here, then we need a way to remove this spare...
    336  1.6  oster 	 that should be easier to do here than if we are "live"...
    337  1.1  oster 
    338  1.6  oster 	 */
    339  1.1  oster 
    340  1.6  oster 	rf_UnconfigureVnodes( raidPtr );
    341  1.1  oster 
    342  1.5  oster 	return (ret);
    343  1.1  oster }
    344  1.1  oster 
    345  1.1  oster 
    346  1.1  oster 
    347  1.1  oster /* configure a single disk in the array */
    348  1.5  oster int
    349  1.6  oster rf_ConfigureDisk(raidPtr, buf, diskPtr, row, col)
    350  1.6  oster 	RF_Raid_t *raidPtr;
    351  1.5  oster 	char   *buf;
    352  1.5  oster 	RF_RaidDisk_t *diskPtr;
    353  1.5  oster 	RF_RowCol_t row;
    354  1.5  oster 	RF_RowCol_t col;
    355  1.1  oster {
    356  1.5  oster 	char   *p;
    357  1.5  oster 	int     retcode;
    358  1.1  oster 
    359  1.1  oster 	struct partinfo dpart;
    360  1.1  oster 	struct vnode *vp;
    361  1.1  oster 	struct vattr va;
    362  1.1  oster 	struct proc *proc;
    363  1.5  oster 	int     error;
    364  1.1  oster 
    365  1.5  oster 	retcode = 0;
    366  1.5  oster 	p = rf_find_non_white(buf);
    367  1.5  oster 	if (p[strlen(p) - 1] == '\n') {
    368  1.5  oster 		/* strip off the newline */
    369  1.5  oster 		p[strlen(p) - 1] = '\0';
    370  1.5  oster 	}
    371  1.5  oster 	(void) strcpy(diskPtr->devname, p);
    372  1.1  oster 
    373  1.5  oster 	proc = raidPtr->proc;	/* XXX Yes, this is not nice.. */
    374  1.5  oster 
    375  1.5  oster 	/* Let's start by claiming the component is fine and well... */
    376  1.5  oster 	diskPtr->status = rf_ds_optimal;
    377  1.5  oster 
    378  1.5  oster 	raidPtr->raid_cinfo[row][col].ci_vp = NULL;
    379  1.5  oster 	raidPtr->raid_cinfo[row][col].ci_dev = NULL;
    380  1.5  oster 
    381  1.5  oster 	error = raidlookup(diskPtr->devname, proc, &vp);
    382  1.5  oster 	if (error) {
    383  1.5  oster 		printf("raidlookup on device: %s failed!\n", diskPtr->devname);
    384  1.5  oster 		if (error == ENXIO) {
    385  1.6  oster 			/* the component isn't there... must be dead :-( */
    386  1.5  oster 			diskPtr->status = rf_ds_failed;
    387  1.5  oster 		} else {
    388  1.5  oster 			return (error);
    389  1.5  oster 		}
    390  1.5  oster 	}
    391  1.5  oster 	if (diskPtr->status == rf_ds_optimal) {
    392  1.5  oster 
    393  1.5  oster 		if ((error = VOP_GETATTR(vp, &va, proc->p_ucred, proc)) != 0) {
    394  1.5  oster 			return (error);
    395  1.5  oster 		}
    396  1.5  oster 		error = VOP_IOCTL(vp, DIOCGPART, (caddr_t) & dpart,
    397  1.6  oster 				  FREAD, proc->p_ucred, proc);
    398  1.5  oster 		if (error) {
    399  1.5  oster 			return (error);
    400  1.5  oster 		}
    401  1.6  oster 
    402  1.5  oster 		diskPtr->blockSize = dpart.disklab->d_secsize;
    403  1.6  oster 
    404  1.5  oster 		diskPtr->numBlocks = dpart.part->p_size - rf_protectedSectors;
    405  1.6  oster 
    406  1.5  oster 		raidPtr->raid_cinfo[row][col].ci_vp = vp;
    407  1.5  oster 		raidPtr->raid_cinfo[row][col].ci_dev = va.va_rdev;
    408  1.6  oster 
    409  1.6  oster 		diskPtr->dev = va.va_rdev;
    410  1.6  oster 
    411  1.6  oster 		/* we allow the user to specify that only a fraction of the
    412  1.6  oster 		 * disks should be used this is just for debug:  it speeds up
    413  1.6  oster 		 * the parity scan */
    414  1.6  oster 		diskPtr->numBlocks = diskPtr->numBlocks *
    415  1.6  oster 			rf_sizePercentage / 100;
    416  1.6  oster 	}
    417  1.6  oster 	return (0);
    418  1.6  oster }
    419  1.6  oster 
    420  1.6  oster /*
    421  1.6  oster 
    422  1.6  oster    rf_CheckLabels() - check all the component labels for consistency.
    423  1.6  oster    Return an error if there is anything major amiss.
    424  1.6  oster 
    425  1.6  oster  */
    426  1.1  oster 
    427  1.6  oster int
    428  1.6  oster rf_CheckLabels( raidPtr, cfgPtr )
    429  1.6  oster 	RF_Raid_t *raidPtr;
    430  1.6  oster 	RF_Config_t *cfgPtr;
    431  1.6  oster {
    432  1.6  oster 	int r,c;
    433  1.6  oster 	char *dev_name;
    434  1.6  oster 	RF_ComponentLabel_t *ci_label;
    435  1.6  oster 	int version = 0;
    436  1.6  oster 	int serial_number = 0;
    437  1.6  oster 	int mod_counter = 0;
    438  1.6  oster 	int fatal_error = 0;
    439  1.6  oster 	int disk_num = 0;
    440  1.6  oster 
    441  1.6  oster 	for (r = 0; r < raidPtr->numRow; r++) {
    442  1.6  oster 		for (c = 0; c < raidPtr->numCol; c++) {
    443  1.6  oster 			dev_name = &cfgPtr->devnames[r][c][0];
    444  1.6  oster 			ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
    445  1.6  oster 
    446  1.6  oster 			printf("Component label for %s being configured at row: %d col: %d\n", dev_name, r, c );
    447  1.6  oster 			printf("         Row: %d Column: %d Num Rows: %d Num Columns: %d\n", 			       ci_label->row, ci_label->column,
    448  1.6  oster 			       ci_label->num_rows, ci_label->num_columns);
    449  1.6  oster 			printf("         Version: %d Serial Number: %d Clean: %d Status: %d\n", ci_label->version, ci_label->serial_number,
    450  1.6  oster 			       ci_label->clean, ci_label->status );
    451  1.6  oster 
    452  1.6  oster 			if ( r !=0 && c != 0) {
    453  1.6  oster 				if (serial_number != ci_label->serial_number) {
    454  1.6  oster 					printf("%s has a different %s\n",
    455  1.6  oster 					       dev_name, "serial number!");
    456  1.6  oster 					fatal_error = 1;
    457  1.6  oster 				}
    458  1.6  oster 				if (version != ci_label->version) {
    459  1.6  oster 					printf("%s has a different %s\n",
    460  1.6  oster 					       dev_name, "version!");
    461  1.6  oster 					fatal_error = 1;
    462  1.6  oster 				}
    463  1.6  oster 				if (mod_counter != ci_label->mod_counter) {
    464  1.6  oster 					printf("%s has a different modfication count!\n",dev_name);
    465  1.6  oster 				}
    466  1.6  oster 			} else {
    467  1.6  oster 				serial_number = ci_label->serial_number;
    468  1.6  oster 				version = ci_label->version;
    469  1.6  oster 				mod_counter = ci_label->mod_counter;
    470  1.6  oster 			}
    471  1.6  oster 
    472  1.6  oster 			if (r != ci_label->row) {
    473  1.6  oster 				printf("Row out of alignment for: %s\n",
    474  1.6  oster 				       dev_name);
    475  1.6  oster 				fatal_error = 1;
    476  1.6  oster 			}
    477  1.6  oster 			if (c != ci_label->column) {
    478  1.6  oster 				printf("Column out of alignment for: %s\n",
    479  1.6  oster 				       dev_name);
    480  1.6  oster 				fatal_error = 1;
    481  1.6  oster 			}
    482  1.6  oster 			if (raidPtr->numRow != ci_label->num_rows) {
    483  1.6  oster 				printf("Number of rows do not match for: %s\n",
    484  1.6  oster 				       dev_name);
    485  1.6  oster 				fatal_error = 1;
    486  1.6  oster 			}
    487  1.6  oster 			if (raidPtr->numCol != ci_label->num_columns) {
    488  1.6  oster 				printf("Number of columns do not match for: %s\n",
    489  1.6  oster 				       dev_name);
    490  1.6  oster 				fatal_error = 1;
    491  1.6  oster 			}
    492  1.6  oster 			if (ci_label->clean == 0) {
    493  1.6  oster 				/* it's not clean, but it's not fatal */
    494  1.6  oster 				printf("%s is not clean!\n", dev_name);
    495  1.6  oster 			}
    496  1.6  oster 			disk_num++;
    497  1.6  oster 		}
    498  1.6  oster 	}
    499  1.6  oster 
    500  1.6  oster 	return(fatal_error);
    501  1.6  oster }
    502  1.6  oster 
    503  1.6  oster 
    504  1.6  oster int rf_add_hot_spare(RF_Raid_t *, RF_HotSpare_t *);
    505  1.6  oster int
    506  1.6  oster rf_add_hot_spare(raidPtr, sparePtr)
    507  1.6  oster 	RF_Raid_t *raidPtr;
    508  1.6  oster 	RF_HotSpare_t *sparePtr;
    509  1.6  oster {
    510  1.6  oster 	RF_RaidDisk_t *disks;
    511  1.6  oster 	int ret;
    512  1.6  oster 	unsigned int bs;
    513  1.6  oster 	int spare_number;
    514  1.6  oster 
    515  1.6  oster 	printf("Just in rf_add_hot_spare: %d\n",raidPtr->numSpare);
    516  1.6  oster 	printf("Num col: %d\n",raidPtr->numCol);
    517  1.6  oster 	if (raidPtr->numSpare >= RF_MAXSPARE) {
    518  1.6  oster 		RF_ERRORMSG1("Too many spares: %d\n", raidPtr->numSpare);
    519  1.6  oster 		return(EINVAL);
    520  1.6  oster 	}
    521  1.6  oster 
    522  1.6  oster 	/* the beginning of the spares... */
    523  1.6  oster 	disks = &raidPtr->Disks[0][raidPtr->numCol];
    524  1.6  oster 
    525  1.6  oster 	spare_number = raidPtr->numSpare;
    526  1.1  oster 
    527  1.6  oster 	ret = rf_ConfigureDisk(raidPtr, sparePtr->spare_name,
    528  1.6  oster 			       &disks[spare_number], 0,
    529  1.6  oster 			       raidPtr->numCol + spare_number);
    530  1.1  oster 
    531  1.6  oster 	if (ret)
    532  1.6  oster 		goto fail;
    533  1.6  oster 	if (disks[spare_number].status != rf_ds_optimal) {
    534  1.6  oster 		RF_ERRORMSG1("Warning: spare disk %s failed TUR\n",
    535  1.6  oster 			     sparePtr->spare_name);
    536  1.6  oster 		ret=EINVAL;
    537  1.6  oster 		goto fail;
    538  1.6  oster 	} else {
    539  1.6  oster 		disks[spare_number].status = rf_ds_spare;
    540  1.6  oster 		DPRINTF6("Spare Disk %d: dev %s numBlocks %ld blockSize %d (%ld MB)\n", spare_number,
    541  1.6  oster 			 disks[spare_number].devname,
    542  1.6  oster 			 (long int) disks[spare_number].numBlocks,
    543  1.6  oster 			 disks[spare_number].blockSize,
    544  1.6  oster 			 (long int) disks[spare_number].numBlocks *
    545  1.6  oster 			 disks[spare_number].blockSize / 1024 / 1024);
    546  1.6  oster 	}
    547  1.6  oster 
    548  1.1  oster 
    549  1.6  oster 	/* check sizes and block sizes on the spare disk */
    550  1.6  oster 	bs = 1 << raidPtr->logBytesPerSector;
    551  1.6  oster 	if (disks[spare_number].blockSize != bs) {
    552  1.6  oster 		RF_ERRORMSG3("Block size of %d on spare disk %s is not the same as on other disks (%d)\n", disks[spare_number].blockSize, disks[spare_number].devname, bs);
    553  1.6  oster 		ret = EINVAL;
    554  1.6  oster 		goto fail;
    555  1.6  oster 	}
    556  1.6  oster 	if (disks[spare_number].numBlocks < raidPtr->sectorsPerDisk) {
    557  1.6  oster 		RF_ERRORMSG3("Spare disk %s (%d blocks) is too small to serve as a spare (need %ld blocks)\n",
    558  1.6  oster 			     disks[spare_number].devname,
    559  1.6  oster 			     disks[spare_number].blockSize,
    560  1.6  oster 			     (long int) raidPtr->sectorsPerDisk);
    561  1.6  oster 		ret = EINVAL;
    562  1.6  oster 		goto fail;
    563  1.6  oster 	} else {
    564  1.6  oster 		if (disks[spare_number].numBlocks >
    565  1.6  oster 		    raidPtr->sectorsPerDisk) {
    566  1.6  oster 			RF_ERRORMSG2("Warning: truncating spare disk %s to %ld blocks\n", disks[spare_number].devname,
    567  1.6  oster 				     (long int) raidPtr->sectorsPerDisk);
    568  1.6  oster 
    569  1.6  oster 			disks[spare_number].numBlocks = raidPtr->sectorsPerDisk;
    570  1.6  oster 		}
    571  1.5  oster 	}
    572  1.6  oster 
    573  1.6  oster 	raidPtr->numSpare++;
    574  1.6  oster 
    575  1.5  oster 	return (0);
    576  1.6  oster 
    577  1.6  oster fail:
    578  1.6  oster 	return(ret);
    579  1.6  oster }
    580  1.6  oster 
    581  1.6  oster int
    582  1.6  oster rf_remove_hot_spare(raidPtr,sparePtr)
    583  1.6  oster 	RF_Raid_t *raidPtr;
    584  1.6  oster 	RF_HotSpare_t *sparePtr;
    585  1.6  oster {
    586  1.6  oster 	int spare_number;
    587  1.6  oster 
    588  1.6  oster 
    589  1.6  oster 	if (raidPtr->numSpare==0) {
    590  1.6  oster 		printf("No spares to remove!\n");
    591  1.6  oster 		return(EINVAL);
    592  1.6  oster 	}
    593  1.6  oster 
    594  1.6  oster 	spare_number = sparePtr->spare_number;
    595  1.6  oster 
    596  1.6  oster 	return(EINVAL); /* XXX not implemented yet */
    597  1.6  oster #if 0
    598  1.6  oster 	if (spare_number < 0 || spare_number > raidPtr->numSpare) {
    599  1.6  oster 		return(EINVAL);
    600  1.6  oster 	}
    601  1.6  oster 
    602  1.6  oster 	/* verify that this spare isn't in use... */
    603  1.6  oster 
    604  1.6  oster 
    605  1.6  oster 
    606  1.6  oster 
    607  1.6  oster 	/* it's gone.. */
    608  1.6  oster 
    609  1.6  oster 	raidPtr->numSpare--;
    610  1.6  oster 
    611  1.6  oster 	return(0);
    612  1.6  oster #endif
    613  1.1  oster }
    614  1.6  oster 
    615  1.6  oster 
    616