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