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