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