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