Home | History | Annotate | Line # | Download | only in raidframe
rf_disks.c revision 1.5
      1  1.5  oster /*	$NetBSD: rf_disks.c,v 1.5 1999/02/05 00:06:09 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 #include "rf_types.h"
     34  1.1  oster #include "rf_raid.h"
     35  1.1  oster #include "rf_alloclist.h"
     36  1.1  oster #include "rf_utils.h"
     37  1.1  oster #include "rf_configure.h"
     38  1.1  oster #include "rf_general.h"
     39  1.1  oster #if !defined(__NetBSD__)
     40  1.1  oster #include "rf_camlayer.h"
     41  1.1  oster #endif
     42  1.1  oster #include "rf_options.h"
     43  1.1  oster #include "rf_sys.h"
     44  1.1  oster 
     45  1.1  oster #include <sys/types.h>
     46  1.1  oster #include <sys/param.h>
     47  1.1  oster #include <sys/systm.h>
     48  1.1  oster #include <sys/proc.h>
     49  1.1  oster #include <sys/ioctl.h>
     50  1.1  oster #include <sys/fcntl.h>
     51  1.1  oster #include <sys/vnode.h>
     52  1.1  oster 
     53  1.5  oster int raidlookup __P((char *, struct proc * p, struct vnode **));
     54  1.1  oster 
     55  1.1  oster 
     56  1.1  oster #define DPRINTF6(a,b,c,d,e,f) if (rf_diskDebug) printf(a,b,c,d,e,f)
     57  1.1  oster #define DPRINTF7(a,b,c,d,e,f,g) if (rf_diskDebug) printf(a,b,c,d,e,f,g)
     58  1.1  oster 
     59  1.1  oster /****************************************************************************************
     60  1.1  oster  *
     61  1.1  oster  * initialize the disks comprising the array
     62  1.1  oster  *
     63  1.1  oster  * We want the spare disks to have regular row,col numbers so that we can easily
     64  1.1  oster  * substitue a spare for a failed disk.  But, the driver code assumes throughout
     65  1.1  oster  * that the array contains numRow by numCol _non-spare_ disks, so it's not clear
     66  1.1  oster  * how to fit in the spares.  This is an unfortunate holdover from raidSim.  The
     67  1.1  oster  * quick and dirty fix is to make row zero bigger than the rest, and put all the
     68  1.1  oster  * spares in it.  This probably needs to get changed eventually.
     69  1.1  oster  *
     70  1.1  oster  ***************************************************************************************/
     71  1.5  oster int
     72  1.5  oster rf_ConfigureDisks(
     73  1.5  oster     RF_ShutdownList_t ** listp,
     74  1.5  oster     RF_Raid_t * raidPtr,
     75  1.5  oster     RF_Config_t * cfgPtr)
     76  1.1  oster {
     77  1.5  oster 	RF_RaidDisk_t **disks;
     78  1.5  oster 	RF_SectorCount_t min_numblks = (RF_SectorCount_t) 0x7FFFFFFFFFFFLL;
     79  1.5  oster 	RF_RowCol_t r, c;
     80  1.5  oster 	int     bs, ret;
     81  1.5  oster 	unsigned i, count, foundone = 0, numFailuresThisRow;
     82  1.5  oster 	RF_DiskOp_t *rdcap_op = NULL, *tur_op = NULL;
     83  1.5  oster 	int     num_rows_done, num_cols_done;
     84  1.1  oster 
     85  1.5  oster 	struct proc *proc = 0;
     86  1.1  oster #ifndef __NetBSD__
     87  1.5  oster 	ret = rf_SCSI_AllocReadCapacity(&rdcap_op);
     88  1.5  oster 	if (ret)
     89  1.5  oster 		goto fail;
     90  1.5  oster 	ret = rf_SCSI_AllocTUR(&tur_op);
     91  1.5  oster 	if (ret)
     92  1.5  oster 		goto fail;
     93  1.5  oster #endif				/* !__NetBSD__ */
     94  1.5  oster 
     95  1.5  oster 	num_rows_done = 0;
     96  1.5  oster 	num_cols_done = 0;
     97  1.5  oster 
     98  1.5  oster 
     99  1.5  oster 	RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *), (RF_RaidDisk_t **), raidPtr->cleanupList);
    100  1.5  oster 	if (disks == NULL) {
    101  1.5  oster 		ret = ENOMEM;
    102  1.5  oster 		goto fail;
    103  1.5  oster 	}
    104  1.5  oster 	raidPtr->Disks = disks;
    105  1.5  oster 
    106  1.5  oster 
    107  1.5  oster 	proc = raidPtr->proc;	/* Blah XXX */
    108  1.5  oster 
    109  1.5  oster 	/* get space for the device-specific stuff... */
    110  1.5  oster 	RF_CallocAndAdd(raidPtr->raid_cinfo, raidPtr->numRow,
    111  1.5  oster 	    sizeof(struct raidcinfo *), (struct raidcinfo **),
    112  1.5  oster 	    raidPtr->cleanupList);
    113  1.5  oster 	if (raidPtr->raid_cinfo == NULL) {
    114  1.5  oster 		ret = ENOMEM;
    115  1.5  oster 		goto fail;
    116  1.5  oster 	}
    117  1.5  oster 	for (r = 0; r < raidPtr->numRow; r++) {
    118  1.5  oster 		numFailuresThisRow = 0;
    119  1.5  oster 		RF_CallocAndAdd(disks[r], raidPtr->numCol + ((r == 0) ? raidPtr->numSpare : 0), sizeof(RF_RaidDisk_t), (RF_RaidDisk_t *), raidPtr->cleanupList);
    120  1.5  oster 		if (disks[r] == NULL) {
    121  1.5  oster 			ret = ENOMEM;
    122  1.5  oster 			goto fail;
    123  1.5  oster 		}
    124  1.5  oster 		/* get more space for device specific stuff.. */
    125  1.5  oster 		RF_CallocAndAdd(raidPtr->raid_cinfo[r],
    126  1.5  oster 		    raidPtr->numCol + ((r == 0) ? raidPtr->numSpare : 0),
    127  1.5  oster 		    sizeof(struct raidcinfo), (struct raidcinfo *),
    128  1.1  oster 		    raidPtr->cleanupList);
    129  1.5  oster 		if (raidPtr->raid_cinfo[r] == NULL) {
    130  1.5  oster 			ret = ENOMEM;
    131  1.5  oster 			goto fail;
    132  1.5  oster 		}
    133  1.5  oster 		for (c = 0; c < raidPtr->numCol; c++) {
    134  1.5  oster 			ret = rf_ConfigureDisk(raidPtr, &cfgPtr->devnames[r][c][0],
    135  1.5  oster 			    &disks[r][c], rdcap_op, tur_op,
    136  1.5  oster 			    cfgPtr->devs[r][c], r, c);
    137  1.5  oster 			if (ret)
    138  1.5  oster 				goto fail;
    139  1.5  oster 			if (disks[r][c].status != rf_ds_optimal) {
    140  1.5  oster 				numFailuresThisRow++;
    141  1.5  oster 			} else {
    142  1.5  oster 				if (disks[r][c].numBlocks < min_numblks)
    143  1.5  oster 					min_numblks = disks[r][c].numBlocks;
    144  1.5  oster 				DPRINTF7("Disk at row %d col %d: dev %s numBlocks %ld blockSize %d (%ld MB)\n",
    145  1.5  oster 				    r, c, disks[r][c].devname,
    146  1.5  oster 				    (long int) disks[r][c].numBlocks,
    147  1.5  oster 				    disks[r][c].blockSize,
    148  1.5  oster 				    (long int) disks[r][c].numBlocks * disks[r][c].blockSize / 1024 / 1024);
    149  1.5  oster 			}
    150  1.5  oster 			num_cols_done++;
    151  1.5  oster 		}
    152  1.5  oster 		/* XXX fix for n-fault tolerant */
    153  1.5  oster 		if (numFailuresThisRow > 0)
    154  1.5  oster 			raidPtr->status[r] = rf_rs_degraded;
    155  1.5  oster 		num_rows_done++;
    156  1.5  oster 	}
    157  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    158  1.5  oster 	/* we do nothing */
    159  1.1  oster #else
    160  1.5  oster 	rf_SCSI_FreeDiskOp(rdcap_op, 1);
    161  1.5  oster 	rdcap_op = NULL;
    162  1.5  oster 	rf_SCSI_FreeDiskOp(tur_op, 0);
    163  1.5  oster 	tur_op = NULL;
    164  1.1  oster #endif
    165  1.5  oster 	/* all disks must be the same size & have the same block size, bs must
    166  1.5  oster 	 * be a power of 2 */
    167  1.5  oster 	bs = 0;
    168  1.5  oster 	for (foundone = r = 0; !foundone && r < raidPtr->numRow; r++) {
    169  1.5  oster 		for (c = 0; !foundone && c < raidPtr->numCol; c++) {
    170  1.5  oster 			if (disks[r][c].status == rf_ds_optimal) {
    171  1.5  oster 				bs = disks[r][c].blockSize;
    172  1.5  oster 				foundone = 1;
    173  1.5  oster 			}
    174  1.5  oster 		}
    175  1.5  oster 	}
    176  1.5  oster 	if (!foundone) {
    177  1.5  oster 		RF_ERRORMSG("RAIDFRAME: Did not find any live disks in the array.\n");
    178  1.5  oster 		ret = EINVAL;
    179  1.5  oster 		goto fail;
    180  1.5  oster 	}
    181  1.5  oster 	for (count = 0, i = 1; i; i <<= 1)
    182  1.5  oster 		if (bs & i)
    183  1.5  oster 			count++;
    184  1.5  oster 	if (count != 1) {
    185  1.5  oster 		RF_ERRORMSG1("Error: block size on disks (%d) must be a power of 2\n", bs);
    186  1.5  oster 		ret = EINVAL;
    187  1.5  oster 		goto fail;
    188  1.5  oster 	}
    189  1.5  oster 	for (r = 0; r < raidPtr->numRow; r++) {
    190  1.5  oster 		for (c = 0; c < raidPtr->numCol; c++) {
    191  1.5  oster 			if (disks[r][c].status == rf_ds_optimal) {
    192  1.5  oster 				if (disks[r][c].blockSize != bs) {
    193  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);
    194  1.5  oster 					ret = EINVAL;
    195  1.5  oster 					goto fail;
    196  1.5  oster 				}
    197  1.5  oster 				if (disks[r][c].numBlocks != min_numblks) {
    198  1.5  oster 					RF_ERRORMSG3("WARNING: truncating disk at r %d c %d to %d blocks\n",
    199  1.5  oster 					    r, c, (int) min_numblks);
    200  1.5  oster 					disks[r][c].numBlocks = min_numblks;
    201  1.5  oster 				}
    202  1.5  oster 			}
    203  1.5  oster 		}
    204  1.5  oster 	}
    205  1.5  oster 
    206  1.5  oster 	raidPtr->sectorsPerDisk = min_numblks;
    207  1.5  oster 	raidPtr->logBytesPerSector = ffs(bs) - 1;
    208  1.5  oster 	raidPtr->bytesPerSector = bs;
    209  1.5  oster 	raidPtr->sectorMask = bs - 1;
    210  1.5  oster 	return (0);
    211  1.1  oster 
    212  1.1  oster fail:
    213  1.1  oster 
    214  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    215  1.1  oster 
    216  1.5  oster 	for (r = 0; r < raidPtr->numRow; r++) {
    217  1.5  oster 		for (c = 0; c < raidPtr->numCol; c++) {
    218  1.5  oster 			/* Cleanup.. */
    219  1.1  oster #ifdef DEBUG
    220  1.5  oster 			printf("Cleaning up row: %d col: %d\n", r, c);
    221  1.1  oster #endif
    222  1.5  oster 			if (raidPtr->raid_cinfo[r][c].ci_vp) {
    223  1.5  oster 				(void) vn_close(raidPtr->raid_cinfo[r][c].ci_vp,
    224  1.5  oster 				    FREAD | FWRITE, proc->p_ucred, proc);
    225  1.5  oster 			}
    226  1.5  oster 		}
    227  1.5  oster 	}
    228  1.5  oster 	/* Space allocated for raid_vpp will get cleaned up at some other
    229  1.5  oster 	 * point */
    230  1.5  oster 	/* XXX Need more #ifdefs in the above... */
    231  1.1  oster 
    232  1.5  oster #else
    233  1.1  oster 
    234  1.5  oster 	if (rdcap_op)
    235  1.5  oster 		rf_SCSI_FreeDiskOp(rdcap_op, 1);
    236  1.5  oster 	if (tur_op)
    237  1.5  oster 		rf_SCSI_FreeDiskOp(tur_op, 0);
    238  1.1  oster 
    239  1.1  oster #endif
    240  1.5  oster 	return (ret);
    241  1.1  oster }
    242  1.1  oster 
    243  1.1  oster 
    244  1.1  oster /****************************************************************************************
    245  1.1  oster  * set up the data structures describing the spare disks in the array
    246  1.1  oster  * recall from the above comment that the spare disk descriptors are stored
    247  1.1  oster  * in row zero, which is specially expanded to hold them.
    248  1.1  oster  ***************************************************************************************/
    249  1.5  oster int
    250  1.5  oster rf_ConfigureSpareDisks(
    251  1.5  oster     RF_ShutdownList_t ** listp,
    252  1.5  oster     RF_Raid_t * raidPtr,
    253  1.5  oster     RF_Config_t * cfgPtr)
    254  1.1  oster {
    255  1.5  oster 	char    buf[256];
    256  1.5  oster 	int     r, c, i, ret;
    257  1.5  oster 	RF_DiskOp_t *rdcap_op = NULL, *tur_op = NULL;
    258  1.5  oster 	unsigned bs;
    259  1.5  oster 	RF_RaidDisk_t *disks;
    260  1.5  oster 	int     num_spares_done;
    261  1.1  oster 
    262  1.5  oster 	struct proc *proc;
    263  1.1  oster 
    264  1.1  oster #ifndef __NetBSD__
    265  1.5  oster 	ret = rf_SCSI_AllocReadCapacity(&rdcap_op);
    266  1.5  oster 	if (ret)
    267  1.5  oster 		goto fail;
    268  1.5  oster 	ret = rf_SCSI_AllocTUR(&tur_op);
    269  1.5  oster 	if (ret)
    270  1.5  oster 		goto fail;
    271  1.5  oster #endif				/* !__NetBSD__ */
    272  1.5  oster 
    273  1.5  oster 	num_spares_done = 0;
    274  1.5  oster 
    275  1.5  oster 	proc = raidPtr->proc;
    276  1.5  oster 	/* The space for the spares should have already been allocated by
    277  1.5  oster 	 * ConfigureDisks() */
    278  1.5  oster 
    279  1.5  oster 	disks = &raidPtr->Disks[0][raidPtr->numCol];
    280  1.5  oster 	for (i = 0; i < raidPtr->numSpare; i++) {
    281  1.5  oster 		ret = rf_ConfigureDisk(raidPtr, &cfgPtr->spare_names[i][0],
    282  1.5  oster 		    &disks[i], rdcap_op, tur_op,
    283  1.5  oster 		    cfgPtr->spare_devs[i], 0, raidPtr->numCol + i);
    284  1.5  oster 		if (ret)
    285  1.5  oster 			goto fail;
    286  1.5  oster 		if (disks[i].status != rf_ds_optimal) {
    287  1.5  oster 			RF_ERRORMSG1("Warning: spare disk %s failed TUR\n", buf);
    288  1.5  oster 		} else {
    289  1.5  oster 			disks[i].status = rf_ds_spare;	/* change status to
    290  1.5  oster 							 * spare */
    291  1.5  oster 			DPRINTF6("Spare Disk %d: dev %s numBlocks %ld blockSize %d (%ld MB)\n", i,
    292  1.5  oster 			    disks[i].devname,
    293  1.5  oster 			    (long int) disks[i].numBlocks, disks[i].blockSize,
    294  1.5  oster 			    (long int) disks[i].numBlocks * disks[i].blockSize / 1024 / 1024);
    295  1.5  oster 		}
    296  1.5  oster 		num_spares_done++;
    297  1.5  oster 	}
    298  1.1  oster #if defined(__NetBSD__) && (_KERNEL)
    299  1.1  oster 
    300  1.1  oster #else
    301  1.5  oster 	rf_SCSI_FreeDiskOp(rdcap_op, 1);
    302  1.5  oster 	rdcap_op = NULL;
    303  1.5  oster 	rf_SCSI_FreeDiskOp(tur_op, 0);
    304  1.5  oster 	tur_op = NULL;
    305  1.1  oster #endif
    306  1.1  oster 
    307  1.5  oster 	/* check sizes and block sizes on spare disks */
    308  1.5  oster 	bs = 1 << raidPtr->logBytesPerSector;
    309  1.5  oster 	for (i = 0; i < raidPtr->numSpare; i++) {
    310  1.5  oster 		if (disks[i].blockSize != bs) {
    311  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);
    312  1.5  oster 			ret = EINVAL;
    313  1.5  oster 			goto fail;
    314  1.5  oster 		}
    315  1.5  oster 		if (disks[i].numBlocks < raidPtr->sectorsPerDisk) {
    316  1.5  oster 			RF_ERRORMSG3("Spare disk %s (%d blocks) is too small to serve as a spare (need %ld blocks)\n",
    317  1.5  oster 			    disks[i].devname, disks[i].blockSize, (long int) raidPtr->sectorsPerDisk);
    318  1.5  oster 			ret = EINVAL;
    319  1.5  oster 			goto fail;
    320  1.5  oster 		} else
    321  1.5  oster 			if (disks[i].numBlocks > raidPtr->sectorsPerDisk) {
    322  1.5  oster 				RF_ERRORMSG2("Warning: truncating spare disk %s to %ld blocks\n", disks[i].devname, (long int) raidPtr->sectorsPerDisk);
    323  1.5  oster 
    324  1.5  oster 				disks[i].numBlocks = raidPtr->sectorsPerDisk;
    325  1.5  oster 			}
    326  1.5  oster 	}
    327  1.5  oster 
    328  1.5  oster 	return (0);
    329  1.1  oster 
    330  1.1  oster fail:
    331  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    332  1.2  oster 
    333  1.5  oster 	/* Release the hold on the main components.  We've failed to allocate
    334  1.5  oster 	 * a spare, and since we're failing, we need to free things.. */
    335  1.2  oster 
    336  1.5  oster 	for (r = 0; r < raidPtr->numRow; r++) {
    337  1.5  oster 		for (c = 0; c < raidPtr->numCol; c++) {
    338  1.5  oster 			/* Cleanup.. */
    339  1.2  oster #ifdef DEBUG
    340  1.5  oster 			printf("Cleaning up row: %d col: %d\n", r, c);
    341  1.2  oster #endif
    342  1.5  oster 			if (raidPtr->raid_cinfo[r][c].ci_vp) {
    343  1.5  oster 				(void) vn_close(raidPtr->raid_cinfo[r][c].ci_vp,
    344  1.5  oster 				    FREAD | FWRITE, proc->p_ucred, proc);
    345  1.5  oster 			}
    346  1.5  oster 		}
    347  1.5  oster 	}
    348  1.1  oster 
    349  1.5  oster 	for (i = 0; i < raidPtr->numSpare; i++) {
    350  1.5  oster 		/* Cleanup.. */
    351  1.1  oster #ifdef DEBUG
    352  1.5  oster 		printf("Cleaning up spare: %d\n", i);
    353  1.1  oster #endif
    354  1.5  oster 		if (raidPtr->raid_cinfo[0][raidPtr->numCol + i].ci_vp) {
    355  1.5  oster 			(void) vn_close(raidPtr->raid_cinfo[0][raidPtr->numCol + i].ci_vp,
    356  1.5  oster 			    FREAD | FWRITE, proc->p_ucred, proc);
    357  1.5  oster 		}
    358  1.5  oster 	}
    359  1.1  oster 
    360  1.5  oster #else
    361  1.1  oster 
    362  1.5  oster 	if (rdcap_op)
    363  1.5  oster 		rf_SCSI_FreeDiskOp(rdcap_op, 1);
    364  1.5  oster 	if (tur_op)
    365  1.5  oster 		rf_SCSI_FreeDiskOp(tur_op, 0);
    366  1.1  oster 
    367  1.1  oster #endif
    368  1.1  oster 
    369  1.5  oster 	return (ret);
    370  1.1  oster }
    371  1.1  oster 
    372  1.1  oster 
    373  1.1  oster 
    374  1.1  oster /* configure a single disk in the array */
    375  1.5  oster int
    376  1.5  oster rf_ConfigureDisk(raidPtr, buf, diskPtr, rdcap_op, tur_op, dev, row, col)
    377  1.5  oster 	RF_Raid_t *raidPtr;	/* We need this down here too!! GO */
    378  1.5  oster 	char   *buf;
    379  1.5  oster 	RF_RaidDisk_t *diskPtr;
    380  1.5  oster 	RF_DiskOp_t *rdcap_op;
    381  1.5  oster 	RF_DiskOp_t *tur_op;
    382  1.5  oster 	dev_t   dev;		/* device number used only in kernel */
    383  1.5  oster 	RF_RowCol_t row;
    384  1.5  oster 	RF_RowCol_t col;
    385  1.1  oster {
    386  1.5  oster 	char   *p;
    387  1.5  oster 	int     retcode;
    388  1.1  oster 
    389  1.1  oster 	struct partinfo dpart;
    390  1.1  oster 	struct vnode *vp;
    391  1.1  oster 	struct vattr va;
    392  1.1  oster 	struct proc *proc;
    393  1.5  oster 	int     error;
    394  1.1  oster 
    395  1.5  oster 	retcode = 0;
    396  1.5  oster 	p = rf_find_non_white(buf);
    397  1.5  oster 	if (p[strlen(p) - 1] == '\n') {
    398  1.5  oster 		/* strip off the newline */
    399  1.5  oster 		p[strlen(p) - 1] = '\0';
    400  1.5  oster 	}
    401  1.5  oster 	(void) strcpy(diskPtr->devname, p);
    402  1.1  oster 
    403  1.1  oster #ifndef __NetBSD__
    404  1.5  oster 	/* get bus, target, lun */
    405  1.5  oster 	retcode = rf_extract_ids(p, &busid, &targid, &lun);
    406  1.5  oster 	if (retcode)
    407  1.5  oster 		return (retcode);
    408  1.5  oster 
    409  1.5  oster 	/* required in kernel, nop at user level */
    410  1.5  oster 	retcode = rf_SCSI_OpenUnit(dev);
    411  1.5  oster 	if (retcode)
    412  1.5  oster 		return (retcode);
    413  1.5  oster 
    414  1.5  oster 	diskPtr->dev = dev;
    415  1.5  oster 	if (rf_SCSI_DoTUR(tur_op, (u_char) busid, (u_char) targid, (u_char) lun, dev)) {
    416  1.5  oster 		RF_ERRORMSG1("Disk %s failed TUR.  Marked as dead.\n", diskPtr->devname);
    417  1.5  oster 		diskPtr->status = rf_ds_failed;
    418  1.5  oster 	} else {
    419  1.5  oster 		diskPtr->status = rf_ds_optimal;
    420  1.5  oster 		retcode = rf_SCSI_DoReadCapacity(raidPtr, rdcap_op, busid, targid, lun, dev,
    421  1.5  oster 		    &diskPtr->numBlocks, &diskPtr->blockSize, diskPtr->devname);
    422  1.5  oster 		if (retcode)
    423  1.5  oster 			return (retcode);
    424  1.5  oster 
    425  1.5  oster 		/* we allow the user to specify that only a fraction of the
    426  1.5  oster 		 * disks should be used this is just for debug:  it speeds up
    427  1.5  oster 		 * the parity scan */
    428  1.5  oster 		diskPtr->numBlocks = diskPtr->numBlocks * rf_sizePercentage / 100;
    429  1.5  oster 	}
    430  1.1  oster #endif
    431  1.5  oster 
    432  1.5  oster 	proc = raidPtr->proc;	/* XXX Yes, this is not nice.. */
    433  1.5  oster 
    434  1.5  oster 	/* Let's start by claiming the component is fine and well... */
    435  1.5  oster 	/* XXX not the case if the disk is toast.. */
    436  1.5  oster 	diskPtr->status = rf_ds_optimal;
    437  1.5  oster 
    438  1.5  oster 
    439  1.5  oster 	raidPtr->raid_cinfo[row][col].ci_vp = NULL;
    440  1.5  oster 	raidPtr->raid_cinfo[row][col].ci_dev = NULL;
    441  1.5  oster 
    442  1.5  oster 	error = raidlookup(diskPtr->devname, proc, &vp);
    443  1.5  oster 	if (error) {
    444  1.5  oster 		printf("raidlookup on device: %s failed!\n", diskPtr->devname);
    445  1.5  oster 		if (error == ENXIO) {
    446  1.5  oster 			/* XXX the component isn't there... must be dead :-( */
    447  1.5  oster 			diskPtr->status = rf_ds_failed;
    448  1.5  oster 		} else {
    449  1.5  oster 			return (error);
    450  1.5  oster 		}
    451  1.5  oster 	}
    452  1.5  oster 	if (diskPtr->status == rf_ds_optimal) {
    453  1.5  oster 
    454  1.5  oster 		if ((error = VOP_GETATTR(vp, &va, proc->p_ucred, proc)) != 0) {
    455  1.5  oster 			return (error);
    456  1.5  oster 		}
    457  1.5  oster 		error = VOP_IOCTL(vp, DIOCGPART, (caddr_t) & dpart,
    458  1.5  oster 		    FREAD, proc->p_ucred, proc);
    459  1.5  oster 		if (error) {
    460  1.5  oster 			return (error);
    461  1.5  oster 		}
    462  1.5  oster 		diskPtr->blockSize = dpart.disklab->d_secsize;
    463  1.5  oster 
    464  1.5  oster 		diskPtr->numBlocks = dpart.part->p_size - rf_protectedSectors;
    465  1.5  oster 
    466  1.5  oster 		raidPtr->raid_cinfo[row][col].ci_vp = vp;
    467  1.5  oster 		raidPtr->raid_cinfo[row][col].ci_dev = va.va_rdev;
    468  1.1  oster 
    469  1.1  oster #if 0
    470  1.5  oster 		diskPtr->dev = dev;
    471  1.1  oster #endif
    472  1.1  oster 
    473  1.5  oster 		diskPtr->dev = va.va_rdev;	/* XXX or the above? */
    474  1.1  oster 
    475  1.5  oster 		/* we allow the user to specify that only a fraction of the
    476  1.5  oster 		 * disks should be used this is just for debug:  it speeds up
    477  1.5  oster 		 * the parity scan */
    478  1.5  oster 		diskPtr->numBlocks = diskPtr->numBlocks * rf_sizePercentage / 100;
    479  1.1  oster 
    480  1.5  oster 	}
    481  1.5  oster 	return (0);
    482  1.1  oster }
    483