ccd.c revision 1.29 1 /* $NetBSD: ccd.c,v 1.29 1996/03/07 15:00:11 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1988 University of Utah.
41 * Copyright (c) 1990, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * This code is derived from software contributed to Berkeley by
45 * the Systems Programming Group of the University of Utah Computer
46 * Science Department.
47 *
48 * Redistribution and use in source and binary forms, with or without
49 * modification, are permitted provided that the following conditions
50 * are met:
51 * 1. Redistributions of source code must retain the above copyright
52 * notice, this list of conditions and the following disclaimer.
53 * 2. Redistributions in binary form must reproduce the above copyright
54 * notice, this list of conditions and the following disclaimer in the
55 * documentation and/or other materials provided with the distribution.
56 * 3. All advertising materials mentioning features or use of this software
57 * must display the following acknowledgement:
58 * This product includes software developed by the University of
59 * California, Berkeley and its contributors.
60 * 4. Neither the name of the University nor the names of its contributors
61 * may be used to endorse or promote products derived from this software
62 * without specific prior written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
65 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
66 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
67 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
68 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
69 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
70 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
71 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
72 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
73 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74 * SUCH DAMAGE.
75 *
76 * from: Utah $Hdr: cd.c 1.6 90/11/28$
77 *
78 * @(#)cd.c 8.2 (Berkeley) 11/16/93
79 */
80
81 /*
82 * "Concatenated" disk driver.
83 *
84 * Dynamic configuration and disklabel support by:
85 * Jason R. Thorpe <thorpej (at) nas.nasa.gov>
86 * Numerical Aerodynamic Simulation Facility
87 * Mail Stop 258-6
88 * NASA Ames Research Center
89 * Moffett Field, CA 94035
90 *
91 * Mirroring support based on code written by Satoshi Asami
92 * and Nisha Talagala.
93 */
94
95 #include <sys/param.h>
96 #include <sys/systm.h>
97 #include <sys/proc.h>
98 #include <sys/errno.h>
99 #include <sys/buf.h>
100 #include <sys/malloc.h>
101 #include <sys/namei.h>
102 #include <sys/stat.h>
103 #include <sys/ioctl.h>
104 #include <sys/disklabel.h>
105 #include <sys/device.h>
106 #include <sys/disk.h>
107 #include <sys/syslog.h>
108 #include <sys/fcntl.h>
109 #include <sys/vnode.h>
110 #include <sys/cpu.h>
111
112 #include <dev/dev_conf.h>
113 #include <dev/ccdvar.h>
114
115 #if defined(CCDDEBUG) && !defined(DEBUG)
116 #define DEBUG
117 #endif
118
119 #ifdef DEBUG
120 #define CCDB_FOLLOW 0x01
121 #define CCDB_INIT 0x02
122 #define CCDB_IO 0x04
123 #define CCDB_LABEL 0x08
124 #define CCDB_VNODE 0x10
125 int ccddebug = 0x00;
126 #endif
127
128 #define ccdunit(x) DISKUNIT(x)
129
130 struct ccdbuf {
131 struct buf cb_buf; /* new I/O buf */
132 struct buf *cb_obp; /* ptr. to original I/O buf */
133 int cb_unit; /* target unit */
134 int cb_comp; /* target component */
135 int cb_flags; /* misc. flags */
136
137 #define CBF_MIRROR 0x01 /* we're for a mirror component */
138 };
139
140 #define getccdbuf() \
141 ((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK))
142 #define putccdbuf(cbp) \
143 free((caddr_t)(cbp), M_DEVBUF)
144
145 #define CCDLABELDEV(dev) \
146 (MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART))
147
148 /* called by main() at boot time */
149 void ccdattach __P((int));
150
151 /* called by biodone() at interrupt time */
152 void ccdiodone __P((struct buf *));
153 int ccdsize __P((dev_t));
154
155 static void ccdstart __P((struct ccd_softc *, struct buf *));
156 static void ccdinterleave __P((struct ccd_softc *, int));
157 static void ccdintr __P((struct ccd_softc *, struct buf *));
158 static int ccdinit __P((struct ccddevice *, char **, struct proc *));
159 static int ccdlookup __P((char *, struct proc *p, struct vnode **));
160 static void ccdbuffer __P((struct ccd_softc *, struct buf *,
161 daddr_t, caddr_t, long, struct ccdbuf **));
162 static void ccdgetdisklabel __P((dev_t));
163 static void ccdmakedisklabel __P((struct ccd_softc *));
164 static int ccdlock __P((struct ccd_softc *));
165 static void ccdunlock __P((struct ccd_softc *));
166
167 #ifdef DEBUG
168 static void printiinfo __P((struct ccdiinfo *));
169 #endif
170
171 /* Non-private for the benefit of libkvm. */
172 struct ccd_softc *ccd_softc;
173 struct ccddevice *ccddevs;
174 int numccd = 0;
175
176 /*
177 * Called by main() during pseudo-device attachment. All we need
178 * to do is allocate enough space for devices to be configured later.
179 */
180 void
181 ccdattach(num)
182 int num;
183 {
184 if (num <= 0) {
185 #ifdef DIAGNOSTIC
186 panic("ccdattach: count <= 0");
187 #endif
188 return;
189 }
190
191 ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc),
192 M_DEVBUF, M_NOWAIT);
193 ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice),
194 M_DEVBUF, M_NOWAIT);
195 if ((ccd_softc == NULL) || (ccddevs == NULL)) {
196 printf("WARNING: no memory for concatenated disks\n");
197 if (ccd_softc != NULL)
198 free(ccd_softc, M_DEVBUF);
199 if (ccddevs != NULL)
200 free(ccddevs, M_DEVBUF);
201 return;
202 }
203 numccd = num;
204 bzero(ccd_softc, num * sizeof(struct ccd_softc));
205 bzero(ccddevs, num * sizeof(struct ccddevice));
206 }
207
208 static int
209 ccdinit(ccd, cpaths, p)
210 struct ccddevice *ccd;
211 char **cpaths;
212 struct proc *p;
213 {
214 register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit];
215 register struct ccdcinfo *ci = NULL;
216 register size_t size;
217 register int ix;
218 struct vnode *vp;
219 struct vattr va;
220 size_t minsize;
221 int maxsecsize;
222 struct partinfo dpart;
223 struct ccdgeom *ccg = &cs->sc_geom;
224 char tmppath[MAXPATHLEN];
225 int error;
226
227 #ifdef DEBUG
228 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
229 printf("ccdinit: unit %d\n", ccd->ccd_unit);
230 #endif
231
232 cs->sc_size = 0;
233 cs->sc_ileave = ccd->ccd_interleave;
234 cs->sc_nccdisks = ccd->ccd_ndev;
235 sprintf(cs->sc_xname, "ccd%d", ccd->ccd_unit); /* XXX */
236
237 /* Allocate space for the component info. */
238 cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo),
239 M_DEVBUF, M_WAITOK);
240
241 /*
242 * Verify that each component piece exists and record
243 * relevant information about it.
244 */
245 maxsecsize = 0;
246 minsize = 0;
247 for (ix = 0; ix < cs->sc_nccdisks; ix++) {
248 vp = ccd->ccd_vpp[ix];
249 ci = &cs->sc_cinfo[ix];
250 ci->ci_vp = vp;
251
252 /*
253 * Copy in the pathname of the component.
254 */
255 bzero(tmppath, sizeof(tmppath)); /* sanity */
256 error = copyinstr(cpaths[ix], tmppath,
257 MAXPATHLEN, &ci->ci_pathlen);
258 if (error) {
259 #ifdef DEBUG
260 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
261 printf("%s: can't copy path, error = %d\n",
262 cs->sc_xname, error);
263 #endif
264 free(cs->sc_cinfo, M_DEVBUF);
265 return (error);
266 }
267 ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK);
268 bcopy(tmppath, ci->ci_path, ci->ci_pathlen);
269
270 /*
271 * XXX: Cache the component's dev_t.
272 */
273 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
274 #ifdef DEBUG
275 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
276 printf("%s: %s: getattr failed %s = %d\n",
277 cs->sc_xname, ci->ci_path,
278 "error", error);
279 #endif
280 free(ci->ci_path, M_DEVBUF);
281 free(cs->sc_cinfo, M_DEVBUF);
282 return (error);
283 }
284 ci->ci_dev = va.va_rdev;
285
286 /*
287 * Get partition information for the component.
288 */
289 error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart,
290 FREAD, p->p_ucred, p);
291 if (error) {
292 #ifdef DEBUG
293 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
294 printf("%s: %s: ioctl failed, error = %d\n",
295 cs->sc_xname, ci->ci_path, error);
296 #endif
297 free(ci->ci_path, M_DEVBUF);
298 free(cs->sc_cinfo, M_DEVBUF);
299 return (error);
300 }
301 if (dpart.part->p_fstype == FS_BSDFFS) {
302 maxsecsize =
303 ((dpart.disklab->d_secsize > maxsecsize) ?
304 dpart.disklab->d_secsize : maxsecsize);
305 size = dpart.part->p_size;
306 } else {
307 #ifdef DEBUG
308 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
309 printf("%s: %s: incorrect partition type\n",
310 cs->sc_xname, ci->ci_path);
311 #endif
312 free(ci->ci_path, M_DEVBUF);
313 free(cs->sc_cinfo, M_DEVBUF);
314 return (EFTYPE);
315 }
316
317 /*
318 * Calculate the size, truncating to an interleave
319 * boundary if necessary.
320 */
321 if (cs->sc_ileave > 1)
322 size -= size % cs->sc_ileave;
323
324 if (size == 0) {
325 #ifdef DEBUG
326 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
327 printf("%s: %s: size == 0\n",
328 cs->sc_xname, ci->ci_path);
329 #endif
330 free(ci->ci_path, M_DEVBUF);
331 free(cs->sc_cinfo, M_DEVBUF);
332 return (ENODEV);
333 }
334
335 if (minsize == 0 || size < minsize)
336 minsize = size;
337 ci->ci_size = size;
338 cs->sc_size += size;
339 }
340
341 /*
342 * Don't allow the interleave to be smaller than
343 * the biggest component sector.
344 */
345 if ((cs->sc_ileave > 0) &&
346 (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) {
347 #ifdef DEBUG
348 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
349 printf("%s: interleave must be at least %d\n",
350 cs->sc_xname, (maxsecsize / DEV_BSIZE));
351 #endif
352 free(ci->ci_path, M_DEVBUF);
353 free(cs->sc_cinfo, M_DEVBUF);
354 return (EINVAL);
355 }
356
357 /*
358 * Mirroring support requires uniform interleave and
359 * and even number of components.
360 */
361 if (ccd->ccd_flags & CCDF_MIRROR) {
362 ccd->ccd_flags |= CCDF_UNIFORM;
363 if (cs->sc_ileave == 0) {
364 #ifdef DEBUG
365 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
366 printf("%s: mirroring requires interleave\n",
367 cs->sc_xname);
368 #endif
369 free(ci->ci_path, M_DEVBUF);
370 free(cs->sc_cinfo, M_DEVBUF);
371 return (EINVAL);
372 }
373 if (cs->sc_nccdisks % 2) {
374 #ifdef DEBUG
375 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
376 printf("%s: mirroring requires even # of components\n",
377 cs->sc_xname);
378 #endif
379 free(ci->ci_path, M_DEVBUF);
380 free(cs->sc_cinfo, M_DEVBUF);
381 return (EINVAL);
382 }
383 }
384
385 /*
386 * If uniform interleave is desired set all sizes to that of
387 * the smallest component.
388 */
389 if (ccd->ccd_flags & CCDF_UNIFORM) {
390 for (ci = cs->sc_cinfo;
391 ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
392 ci->ci_size = minsize;
393
394 if (ccd->ccd_flags & CCDF_MIRROR)
395 cs->sc_size = (cs->sc_nccdisks / 2) * minsize;
396 else
397 cs->sc_size = cs->sc_nccdisks * minsize;
398 }
399
400 /*
401 * Construct the interleave table.
402 */
403 ccdinterleave(cs, ccd->ccd_unit);
404
405 /*
406 * Create pseudo-geometry based on 1MB cylinders. It's
407 * pretty close.
408 */
409 ccg->ccg_secsize = DEV_BSIZE;
410 ccg->ccg_ntracks = 1;
411 ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize);
412 ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors;
413
414 cs->sc_flags |= CCDF_INITED;
415 cs->sc_cflags = ccd->ccd_flags; /* So we can find out later... */
416 cs->sc_unit = ccd->ccd_unit;
417
418 return (0);
419 }
420
421 static void
422 ccdinterleave(cs, unit)
423 register struct ccd_softc *cs;
424 int unit;
425 {
426 register struct ccdcinfo *ci, *smallci;
427 register struct ccdiinfo *ii;
428 register daddr_t bn, lbn;
429 register int ix;
430 u_long size;
431
432 #ifdef DEBUG
433 if (ccddebug & CCDB_INIT)
434 printf("ccdinterleave(%p): ileave %d\n", cs, cs->sc_ileave);
435 #endif
436 /*
437 * Allocate an interleave table.
438 * Chances are this is too big, but we don't care.
439 */
440 size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo);
441 cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
442 bzero((caddr_t)cs->sc_itable, size);
443
444 /*
445 * Trivial case: no interleave (actually interleave of disk size).
446 * Each table entry represents a single component in its entirety.
447 */
448 if (cs->sc_ileave == 0) {
449 bn = 0;
450 ii = cs->sc_itable;
451
452 for (ix = 0; ix < cs->sc_nccdisks; ix++) {
453 /* Allocate space for ii_index. */
454 ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
455 ii->ii_ndisk = 1;
456 ii->ii_startblk = bn;
457 ii->ii_startoff = 0;
458 ii->ii_index[0] = ix;
459 bn += cs->sc_cinfo[ix].ci_size;
460 ii++;
461 }
462 ii->ii_ndisk = 0;
463 #ifdef DEBUG
464 if (ccddebug & CCDB_INIT)
465 printiinfo(cs->sc_itable);
466 #endif
467 return;
468 }
469
470 /*
471 * The following isn't fast or pretty; it doesn't have to be.
472 */
473 size = 0;
474 bn = lbn = 0;
475 for (ii = cs->sc_itable; ; ii++) {
476 /* Allocate space for ii_index. */
477 ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks),
478 M_DEVBUF, M_WAITOK);
479
480 /*
481 * Locate the smallest of the remaining components
482 */
483 smallci = NULL;
484 for (ci = cs->sc_cinfo;
485 ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
486 if (ci->ci_size > size &&
487 (smallci == NULL ||
488 ci->ci_size < smallci->ci_size))
489 smallci = ci;
490
491 /*
492 * Nobody left, all done
493 */
494 if (smallci == NULL) {
495 ii->ii_ndisk = 0;
496 break;
497 }
498
499 /*
500 * Record starting logical block and component offset
501 */
502 ii->ii_startblk = bn / cs->sc_ileave;
503 ii->ii_startoff = lbn;
504
505 /*
506 * Determine how many disks take part in this interleave
507 * and record their indices.
508 */
509 ix = 0;
510 for (ci = cs->sc_cinfo;
511 ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
512 if (ci->ci_size >= smallci->ci_size)
513 ii->ii_index[ix++] = ci - cs->sc_cinfo;
514 ii->ii_ndisk = ix;
515 bn += ix * (smallci->ci_size - size);
516 lbn = smallci->ci_size / cs->sc_ileave;
517 size = smallci->ci_size;
518 }
519 #ifdef DEBUG
520 if (ccddebug & CCDB_INIT)
521 printiinfo(cs->sc_itable);
522 #endif
523 }
524
525 /* ARGSUSED */
526 int
527 ccdopen(dev, flags, fmt, p)
528 dev_t dev;
529 int flags, fmt;
530 struct proc *p;
531 {
532 int unit = ccdunit(dev);
533 struct ccd_softc *cs;
534 struct disklabel *lp;
535 int error = 0, part, pmask;
536
537 #ifdef DEBUG
538 if (ccddebug & CCDB_FOLLOW)
539 printf("ccdopen(%x, %x)\n", dev, flags);
540 #endif
541 if (unit >= numccd)
542 return (ENXIO);
543 cs = &ccd_softc[unit];
544
545 if ((error = ccdlock(cs)) != 0)
546 return (error);
547
548 lp = cs->sc_dkdev.dk_label;
549
550 part = DISKPART(dev);
551 pmask = (1 << part);
552
553 /*
554 * If we're initialized, check to see if there are any other
555 * open partitions. If not, then it's safe to update
556 * the in-core disklabel.
557 */
558 if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0))
559 ccdgetdisklabel(dev);
560
561 /* Check that the partition exists. */
562 if (part != RAW_PART) {
563 if (((cs->sc_flags & CCDF_INITED) == 0) ||
564 ((part > lp->d_npartitions) ||
565 (lp->d_partitions[part].p_fstype == FS_UNUSED))) {
566 error = ENXIO;
567 goto done;
568 }
569 }
570
571 /* Prevent our unit from being unconfigured while open. */
572 switch (fmt) {
573 case S_IFCHR:
574 cs->sc_dkdev.dk_copenmask |= pmask;
575 break;
576
577 case S_IFBLK:
578 cs->sc_dkdev.dk_bopenmask |= pmask;
579 break;
580 }
581 cs->sc_dkdev.dk_openmask =
582 cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
583
584 done:
585 ccdunlock(cs);
586 return (0);
587 }
588
589 /* ARGSUSED */
590 int
591 ccdclose(dev, flags, fmt, p)
592 dev_t dev;
593 int flags, fmt;
594 struct proc *p;
595 {
596 int unit = ccdunit(dev);
597 struct ccd_softc *cs;
598 int error = 0, part;
599
600 #ifdef DEBUG
601 if (ccddebug & CCDB_FOLLOW)
602 printf("ccdclose(%x, %x)\n", dev, flags);
603 #endif
604
605 if (unit >= numccd)
606 return (ENXIO);
607 cs = &ccd_softc[unit];
608
609 if ((error = ccdlock(cs)) != 0)
610 return (error);
611
612 part = DISKPART(dev);
613
614 /* ...that much closer to allowing unconfiguration... */
615 switch (fmt) {
616 case S_IFCHR:
617 cs->sc_dkdev.dk_copenmask &= ~(1 << part);
618 break;
619
620 case S_IFBLK:
621 cs->sc_dkdev.dk_bopenmask &= ~(1 << part);
622 break;
623 }
624 cs->sc_dkdev.dk_openmask =
625 cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
626
627 ccdunlock(cs);
628 return (0);
629 }
630
631 void
632 ccdstrategy(bp)
633 register struct buf *bp;
634 {
635 register int unit = ccdunit(bp->b_dev);
636 register struct ccd_softc *cs = &ccd_softc[unit];
637 register int s;
638 int wlabel;
639 struct disklabel *lp;
640
641 #ifdef DEBUG
642 if (ccddebug & CCDB_FOLLOW)
643 printf("ccdstrategy(%p): unit %d\n", bp, unit);
644 #endif
645 if ((cs->sc_flags & CCDF_INITED) == 0) {
646 bp->b_error = ENXIO;
647 bp->b_flags |= B_ERROR;
648 goto done;
649 }
650
651 /* If it's a nil transfer, wake up the top half now. */
652 if (bp->b_bcount == 0)
653 goto done;
654
655 lp = cs->sc_dkdev.dk_label;
656
657 /*
658 * Do bounds checking and adjust transfer. If there's an
659 * error, the bounds check will flag that for us.
660 */
661 wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
662 if (DISKPART(bp->b_dev) != RAW_PART)
663 if (bounds_check_with_label(bp, lp, wlabel) <= 0)
664 goto done;
665
666 bp->b_resid = bp->b_bcount;
667
668 /*
669 * "Start" the unit.
670 */
671 s = splbio();
672 ccdstart(cs, bp);
673 splx(s);
674 return;
675 done:
676 biodone(bp);
677 }
678
679 static void
680 ccdstart(cs, bp)
681 register struct ccd_softc *cs;
682 register struct buf *bp;
683 {
684 register long bcount, rcount;
685 struct ccdbuf *cbp[4];
686 caddr_t addr;
687 daddr_t bn;
688 struct partition *pp;
689
690 #ifdef DEBUG
691 if (ccddebug & CCDB_FOLLOW)
692 printf("ccdstart(%p, %p)\n", cs, bp);
693 #endif
694
695 /* Instrumentation. */
696 disk_busy(&cs->sc_dkdev);
697
698 /*
699 * Translate the partition-relative block number to an absolute.
700 */
701 bn = bp->b_blkno;
702 if (DISKPART(bp->b_dev) != RAW_PART) {
703 pp = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)];
704 bn += pp->p_offset;
705 }
706
707 /*
708 * Allocate component buffers and fire off the requests
709 */
710 addr = bp->b_data;
711 for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
712 ccdbuffer(cs, bp, bn, addr, bcount, cbp);
713 rcount = cbp[0]->cb_buf.b_bcount;
714 if ((cbp[0]->cb_buf.b_flags & B_READ) == 0)
715 cbp[0]->cb_buf.b_vp->v_numoutput++;
716 VOP_STRATEGY(&cbp[0]->cb_buf);
717
718 /*
719 * Mirror requires additional write.
720 */
721 if ((cs->sc_cflags & CCDF_MIRROR) &&
722 ((cbp[0]->cb_buf.b_flags & B_READ) == 0)) {
723 cbp[1]->cb_buf.b_vp->v_numoutput++;
724 VOP_STRATEGY(&cbp[1]->cb_buf);
725 }
726
727 bn += btodb(rcount);
728 addr += rcount;
729 }
730 }
731
732 /*
733 * Build a component buffer header.
734 */
735 static void
736 ccdbuffer(cs, bp, bn, addr, bcount, cbpp)
737 register struct ccd_softc *cs;
738 struct buf *bp;
739 daddr_t bn;
740 caddr_t addr;
741 long bcount;
742 struct ccdbuf **cbpp;
743 {
744 register struct ccdcinfo *ci, *ci2 = NULL;
745 register struct ccdbuf *cbp;
746 register daddr_t cbn, cboff;
747
748 #ifdef DEBUG
749 if (ccddebug & CCDB_IO)
750 printf("ccdbuffer(%p, %p, %d, %p, %d)\n",
751 cs, bp, bn, addr, bcount);
752 #endif
753 /*
754 * Determine which component bn falls in.
755 */
756 cbn = bn;
757 cboff = 0;
758
759 /*
760 * Serially concatenated
761 */
762 if (cs->sc_ileave == 0) {
763 register daddr_t sblk;
764
765 sblk = 0;
766 for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
767 sblk += ci->ci_size;
768 cbn -= sblk;
769 }
770 /*
771 * Interleaved
772 */
773 else {
774 register struct ccdiinfo *ii;
775 int ccdisk, off;
776
777 cboff = cbn % cs->sc_ileave;
778 cbn /= cs->sc_ileave;
779 for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
780 if (ii->ii_startblk > cbn)
781 break;
782 ii--;
783 off = cbn - ii->ii_startblk;
784 if (ii->ii_ndisk == 1) {
785 ccdisk = ii->ii_index[0];
786 cbn = ii->ii_startoff + off;
787 } else {
788 if (cs->sc_cflags & CCDF_MIRROR) {
789 ccdisk =
790 ii->ii_index[off % (ii->ii_ndisk / 2)];
791 cbn = ii->ii_startoff +
792 (off / (ii->ii_ndisk / 2));
793 /* Mirrored data */
794 ci2 =
795 &cs->sc_cinfo[ccdisk + (ii->ii_ndisk / 2)];
796 } else {
797 /* Normal case. */
798 ccdisk = ii->ii_index[off % ii->ii_ndisk];
799 cbn = ii->ii_startoff + off / ii->ii_ndisk;
800 }
801 }
802 cbn *= cs->sc_ileave;
803 ci = &cs->sc_cinfo[ccdisk];
804 }
805
806 /*
807 * Fill in the component buf structure.
808 */
809 cbp = getccdbuf();
810 cbp->cb_flags = 0;
811 cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
812 cbp->cb_buf.b_iodone = ccdiodone;
813 cbp->cb_buf.b_proc = bp->b_proc;
814 cbp->cb_buf.b_dev = ci->ci_dev; /* XXX */
815 cbp->cb_buf.b_blkno = cbn + cboff;
816 cbp->cb_buf.b_data = addr;
817 cbp->cb_buf.b_vp = ci->ci_vp;
818 if (cs->sc_ileave == 0)
819 cbp->cb_buf.b_bcount = dbtob(ci->ci_size - cbn);
820 else
821 cbp->cb_buf.b_bcount = dbtob(cs->sc_ileave - cboff);
822 if (cbp->cb_buf.b_bcount > bcount)
823 cbp->cb_buf.b_bcount = bcount;
824
825 /*
826 * context for ccdiodone
827 */
828 cbp->cb_obp = bp;
829 cbp->cb_unit = cs - ccd_softc;
830 cbp->cb_comp = ci - cs->sc_cinfo;
831
832 /* First buffer is dealt with. */
833 cbpp[0] = cbp;
834
835 #ifdef DEBUG
836 if (ccddebug & CCDB_IO)
837 printf(" dev %x(u%d): cbp %p bn %d addr %p bcnt %d\n",
838 ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno,
839 cbp->cb_buf.b_data, cbp->cb_buf.b_bcount);
840 #endif
841
842 /*
843 * Mirrors have an additional write operation that is nearly
844 * identical to the first.
845 */
846 if ((cs->sc_cflags & CCDF_MIRROR) &&
847 ((cbp->cb_buf.b_flags & B_READ) == 0)) {
848 cbp = getccdbuf();
849 *cbp = *cbpp[0];
850 cbp->cb_flags = CBF_MIRROR;
851 cbp->cb_buf.b_dev = ci2->ci_dev; /* XXX */
852 cbp->cb_buf.b_vp = ci2->ci_vp;
853 cbp->cb_comp = ci2 - cs->sc_cinfo;
854 cbpp[1] = cbp;
855 }
856 }
857
858 static void
859 ccdintr(cs, bp)
860 register struct ccd_softc *cs;
861 register struct buf *bp;
862 {
863
864 #ifdef DEBUG
865 if (ccddebug & CCDB_FOLLOW)
866 printf("ccdintr(%p, %p)\n", cs, bp);
867 #endif
868 /*
869 * Request is done for better or worse, wakeup the top half.
870 */
871 if (bp->b_flags & B_ERROR)
872 bp->b_resid = bp->b_bcount;
873 disk_unbusy(&cs->sc_dkdev, (bp->b_bcount - bp->b_resid));
874 biodone(bp);
875 }
876
877 /*
878 * Called at interrupt time.
879 * Mark the component as done and if all components are done,
880 * take a ccd interrupt.
881 */
882 void
883 ccdiodone(vbp)
884 struct buf *vbp;
885 {
886 struct ccdbuf *cbp = (struct ccdbuf *) vbp;
887 register struct buf *bp = cbp->cb_obp;
888 register int unit = cbp->cb_unit;
889 struct ccd_softc *cs = &ccd_softc[unit];
890 int count, cbflags, s;
891 char *comptype;
892
893 s = splbio();
894 #ifdef DEBUG
895 if (ccddebug & CCDB_FOLLOW)
896 printf("ccdiodone(%p)\n", cbp);
897 if (ccddebug & CCDB_IO) {
898 if (cbp->cb_flags & CBF_MIRROR)
899 printf("ccdiodone: mirror component\n");
900 else
901 printf("ccdiodone: bp %p bcount %d resid %d\n",
902 bp, bp->b_bcount, bp->b_resid);
903 printf(" dev %x(u%d), cbp %p bn %d addr %p bcnt %d\n",
904 cbp->cb_buf.b_dev, cbp->cb_comp, cbp,
905 cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,
906 cbp->cb_buf.b_bcount);
907 }
908 #endif
909
910 if (cbp->cb_buf.b_flags & B_ERROR) {
911 if (cbp->cb_flags & CBF_MIRROR)
912 comptype = " (mirror)";
913 else {
914 bp->b_flags |= B_ERROR;
915 bp->b_error = cbp->cb_buf.b_error ?
916 cbp->cb_buf.b_error : EIO;
917 comptype = "";
918 }
919
920 printf("%s: error %d on component %d%s\n",
921 cs->sc_xname, bp->b_error, cbp->cb_comp, comptype);
922 }
923 count = cbp->cb_buf.b_bcount;
924 cbflags = cbp->cb_flags;
925 putccdbuf(cbp);
926
927 /*
928 * If all done, "interrupt".
929 *
930 * Note that mirror component buffers aren't counted against
931 * the original I/O buffer.
932 */
933 if ((cbflags & CBF_MIRROR) == 0) {
934 bp->b_resid -= count;
935 if (bp->b_resid < 0)
936 panic("ccdiodone: count");
937 if (bp->b_resid == 0)
938 ccdintr(&ccd_softc[unit], bp);
939 }
940 splx(s);
941 }
942
943 /* ARGSUSED */
944 int
945 ccdread(dev, uio, flags)
946 dev_t dev;
947 struct uio *uio;
948 int flags;
949 {
950 int unit = ccdunit(dev);
951 struct ccd_softc *cs;
952
953 #ifdef DEBUG
954 if (ccddebug & CCDB_FOLLOW)
955 printf("ccdread(%x, %p)\n", dev, uio);
956 #endif
957 if (unit >= numccd)
958 return (ENXIO);
959 cs = &ccd_softc[unit];
960
961 if ((cs->sc_flags & CCDF_INITED) == 0)
962 return (ENXIO);
963
964 /*
965 * XXX: It's not clear that using minphys() is completely safe,
966 * in particular, for raw I/O. Underlying devices might have some
967 * non-obvious limits, because of the copy to user-space.
968 */
969 return (physio(ccdstrategy, NULL, dev, B_READ, minphys, uio));
970 }
971
972 /* ARGSUSED */
973 int
974 ccdwrite(dev, uio, flags)
975 dev_t dev;
976 struct uio *uio;
977 int flags;
978 {
979 int unit = ccdunit(dev);
980 struct ccd_softc *cs;
981
982 #ifdef DEBUG
983 if (ccddebug & CCDB_FOLLOW)
984 printf("ccdwrite(%x, %p)\n", dev, uio);
985 #endif
986 if (unit >= numccd)
987 return (ENXIO);
988 cs = &ccd_softc[unit];
989
990 if ((cs->sc_flags & CCDF_INITED) == 0)
991 return (ENXIO);
992
993 /*
994 * XXX: It's not clear that using minphys() is completely safe,
995 * in particular, for raw I/O. Underlying devices might have some
996 * non-obvious limits, because of the copy to user-space.
997 */
998 return (physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio));
999 }
1000
1001 int
1002 ccdioctl(dev, cmd, data, flag, p)
1003 dev_t dev;
1004 u_long cmd;
1005 caddr_t data;
1006 int flag;
1007 struct proc *p;
1008 {
1009 int unit = ccdunit(dev);
1010 int i, j, lookedup = 0, error = 0;
1011 int part, pmask, s;
1012 struct ccd_softc *cs;
1013 struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;
1014 struct ccddevice ccd;
1015 char **cpp;
1016 struct vnode **vpp;
1017
1018 if (unit >= numccd)
1019 return (ENXIO);
1020 cs = &ccd_softc[unit];
1021
1022 bzero(&ccd, sizeof(ccd));
1023
1024 switch (cmd) {
1025 case CCDIOCSET:
1026 if (cs->sc_flags & CCDF_INITED)
1027 return (EBUSY);
1028
1029 if ((flag & FWRITE) == 0)
1030 return (EBADF);
1031
1032 if ((error = ccdlock(cs)) != 0)
1033 return (error);
1034
1035 /* Fill in some important bits. */
1036 ccd.ccd_unit = unit;
1037 ccd.ccd_interleave = ccio->ccio_ileave;
1038 ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK;
1039
1040 /*
1041 * Allocate space for and copy in the array of
1042 * componet pathnames and device numbers.
1043 */
1044 cpp = malloc(ccio->ccio_ndisks * sizeof(char *),
1045 M_DEVBUF, M_WAITOK);
1046 vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *),
1047 M_DEVBUF, M_WAITOK);
1048
1049 error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp,
1050 ccio->ccio_ndisks * sizeof(char **));
1051 if (error) {
1052 free(vpp, M_DEVBUF);
1053 free(cpp, M_DEVBUF);
1054 ccdunlock(cs);
1055 return (error);
1056 }
1057
1058 #ifdef DEBUG
1059 if (ccddebug & CCDB_INIT)
1060 for (i = 0; i < ccio->ccio_ndisks; ++i)
1061 printf("ccdioctl: component %d: 0x%p\n",
1062 i, cpp[i]);
1063 #endif
1064
1065 for (i = 0; i < ccio->ccio_ndisks; ++i) {
1066 #ifdef DEBUG
1067 if (ccddebug & CCDB_INIT)
1068 printf("ccdioctl: lookedup = %d\n", lookedup);
1069 #endif
1070 if ((error = ccdlookup(cpp[i], p, &vpp[i])) != 0) {
1071 for (j = 0; j < lookedup; ++j)
1072 (void)vn_close(vpp[j], FREAD|FWRITE,
1073 p->p_ucred, p);
1074 free(vpp, M_DEVBUF);
1075 free(cpp, M_DEVBUF);
1076 ccdunlock(cs);
1077 return (error);
1078 }
1079 ++lookedup;
1080 }
1081 ccd.ccd_cpp = cpp;
1082 ccd.ccd_vpp = vpp;
1083 ccd.ccd_ndev = ccio->ccio_ndisks;
1084
1085 /*
1086 * Initialize the ccd. Fills in the softc for us.
1087 */
1088 if ((error = ccdinit(&ccd, cpp, p)) != 0) {
1089 for (j = 0; j < lookedup; ++j)
1090 (void)vn_close(vpp[j], FREAD|FWRITE,
1091 p->p_ucred, p);
1092 bzero(&ccd_softc[unit], sizeof(struct ccd_softc));
1093 free(vpp, M_DEVBUF);
1094 free(cpp, M_DEVBUF);
1095 ccdunlock(cs);
1096 return (error);
1097 }
1098
1099 /*
1100 * The ccd has been successfully initialized, so
1101 * we can place it into the array. Don't try to
1102 * read the disklabel until the disk has been attached,
1103 * because space for the disklabel is allocated
1104 * in disk_attach();
1105 */
1106 bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
1107 ccio->ccio_unit = unit;
1108 ccio->ccio_size = cs->sc_size;
1109
1110 /* Attach the disk. */
1111 cs->sc_dkdev.dk_name = cs->sc_xname;
1112 disk_attach(&cs->sc_dkdev);
1113
1114 /* Try and read the disklabel. */
1115 ccdgetdisklabel(dev);
1116
1117 ccdunlock(cs);
1118
1119 break;
1120
1121 case CCDIOCCLR:
1122 if ((cs->sc_flags & CCDF_INITED) == 0)
1123 return (ENXIO);
1124
1125 if ((flag & FWRITE) == 0)
1126 return (EBADF);
1127
1128 if ((error = ccdlock(cs)) != 0)
1129 return (error);
1130
1131 /*
1132 * Don't unconfigure if any other partitions are open
1133 * or if both the character and block flavors of this
1134 * partition are open.
1135 */
1136 part = DISKPART(dev);
1137 pmask = (1 << part);
1138 if ((cs->sc_dkdev.dk_openmask & ~pmask) ||
1139 ((cs->sc_dkdev.dk_bopenmask & pmask) &&
1140 (cs->sc_dkdev.dk_copenmask & pmask))) {
1141 ccdunlock(cs);
1142 return (EBUSY);
1143 }
1144
1145 /*
1146 * Free ccd_softc information and clear entry.
1147 */
1148
1149 /* Close the components and free their pathnames. */
1150 for (i = 0; i < cs->sc_nccdisks; ++i) {
1151 /*
1152 * XXX: this close could potentially fail and
1153 * cause Bad Things. Maybe we need to force
1154 * the close to happen?
1155 */
1156 #ifdef DEBUG
1157 if (ccddebug & CCDB_VNODE)
1158 vprint("CCDIOCCLR: vnode info",
1159 cs->sc_cinfo[i].ci_vp);
1160 #endif
1161 (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE,
1162 p->p_ucred, p);
1163 free(cs->sc_cinfo[i].ci_path, M_DEVBUF);
1164 }
1165
1166 /* Free interleave index. */
1167 for (i = 0; cs->sc_itable[i].ii_ndisk; ++i)
1168 free(cs->sc_itable[i].ii_index, M_DEVBUF);
1169
1170 /* Free component info and interleave table. */
1171 free(cs->sc_cinfo, M_DEVBUF);
1172 free(cs->sc_itable, M_DEVBUF);
1173 cs->sc_flags &= ~CCDF_INITED;
1174
1175 /*
1176 * Free ccddevice information and clear entry.
1177 */
1178 free(ccddevs[unit].ccd_cpp, M_DEVBUF);
1179 free(ccddevs[unit].ccd_vpp, M_DEVBUF);
1180 bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
1181
1182 /* Detatch the disk. */
1183 disk_detach(&cs->sc_dkdev);
1184
1185 /* This must be atomic. */
1186 s = splhigh();
1187 ccdunlock(cs);
1188 bzero(cs, sizeof(struct ccd_softc));
1189 splx(s);
1190
1191 break;
1192
1193 case DIOCGDINFO:
1194 if ((cs->sc_flags & CCDF_INITED) == 0)
1195 return (ENXIO);
1196
1197 *(struct disklabel *)data = *(cs->sc_dkdev.dk_label);
1198 break;
1199
1200 case DIOCGPART:
1201 if ((cs->sc_flags & CCDF_INITED) == 0)
1202 return (ENXIO);
1203
1204 ((struct partinfo *)data)->disklab = cs->sc_dkdev.dk_label;
1205 ((struct partinfo *)data)->part =
1206 &cs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
1207 break;
1208
1209 case DIOCWDINFO:
1210 case DIOCSDINFO:
1211 if ((cs->sc_flags & CCDF_INITED) == 0)
1212 return (ENXIO);
1213
1214 if ((flag & FWRITE) == 0)
1215 return (EBADF);
1216
1217 if ((error = ccdlock(cs)) != 0)
1218 return (error);
1219
1220 cs->sc_flags |= CCDF_LABELLING;
1221
1222 error = setdisklabel(cs->sc_dkdev.dk_label,
1223 (struct disklabel *)data, 0, cs->sc_dkdev.dk_cpulabel);
1224 if (error == 0) {
1225 if (cmd == DIOCWDINFO)
1226 error = writedisklabel(CCDLABELDEV(dev),
1227 ccdstrategy, cs->sc_dkdev.dk_label,
1228 cs->sc_dkdev.dk_cpulabel);
1229 }
1230
1231 cs->sc_flags &= ~CCDF_LABELLING;
1232
1233 ccdunlock(cs);
1234
1235 if (error)
1236 return (error);
1237 break;
1238
1239 case DIOCWLABEL:
1240 if ((cs->sc_flags & CCDF_INITED) == 0)
1241 return (ENXIO);
1242
1243 if ((flag & FWRITE) == 0)
1244 return (EBADF);
1245 if (*(int *)data != 0)
1246 cs->sc_flags |= CCDF_WLABEL;
1247 else
1248 cs->sc_flags &= ~CCDF_WLABEL;
1249 break;
1250
1251 default:
1252 return (ENOTTY);
1253 }
1254
1255 return (0);
1256 }
1257
1258 int
1259 ccdsize(dev)
1260 dev_t dev;
1261 {
1262 struct ccd_softc *cs;
1263 int part, size;
1264
1265 if (ccdopen(dev, 0, S_IFBLK, curproc))
1266 return (-1);
1267
1268 cs = &ccd_softc[ccdunit(dev)];
1269 part = DISKPART(dev);
1270
1271 if ((cs->sc_flags & CCDF_INITED) == 0)
1272 return (-1);
1273
1274 if (cs->sc_dkdev.dk_label->d_partitions[part].p_fstype != FS_SWAP)
1275 size = -1;
1276 else
1277 size = cs->sc_dkdev.dk_label->d_partitions[part].p_size;
1278
1279 if (ccdclose(dev, 0, S_IFBLK, curproc))
1280 return (-1);
1281
1282 return (size);
1283 }
1284
1285 int
1286 ccddump(dev, blkno, va, size)
1287 dev_t dev;
1288 daddr_t blkno;
1289 caddr_t va;
1290 size_t size;
1291 {
1292
1293 /* Not implemented. */
1294 return ENXIO;
1295 }
1296
1297 /*
1298 * Lookup the provided name in the filesystem. If the file exists,
1299 * is a valid block device, and isn't being used by anyone else,
1300 * set *vpp to the file's vnode.
1301 */
1302 static int
1303 ccdlookup(path, p, vpp)
1304 char *path;
1305 struct proc *p;
1306 struct vnode **vpp; /* result */
1307 {
1308 struct nameidata nd;
1309 struct vnode *vp;
1310 struct vattr va;
1311 int error;
1312
1313 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);
1314 if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
1315 #ifdef DEBUG
1316 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1317 printf("ccdlookup: vn_open error = %d\n", error);
1318 #endif
1319 return (error);
1320 }
1321 vp = nd.ni_vp;
1322
1323 if (vp->v_usecount > 1) {
1324 VOP_UNLOCK(vp);
1325 (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
1326 return (EBUSY);
1327 }
1328
1329 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
1330 #ifdef DEBUG
1331 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1332 printf("ccdlookup: getattr error = %d\n", error);
1333 #endif
1334 VOP_UNLOCK(vp);
1335 (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
1336 return (error);
1337 }
1338
1339 /* XXX: eventually we should handle VREG, too. */
1340 if (va.va_type != VBLK) {
1341 VOP_UNLOCK(vp);
1342 (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
1343 return (ENOTBLK);
1344 }
1345
1346 #ifdef DEBUG
1347 if (ccddebug & CCDB_VNODE)
1348 vprint("ccdlookup: vnode info", vp);
1349 #endif
1350
1351 VOP_UNLOCK(vp);
1352 *vpp = vp;
1353 return (0);
1354 }
1355
1356 /*
1357 * Read the disklabel from the ccd. If one is not present, fake one
1358 * up.
1359 */
1360 static void
1361 ccdgetdisklabel(dev)
1362 dev_t dev;
1363 {
1364 int unit = ccdunit(dev);
1365 struct ccd_softc *cs = &ccd_softc[unit];
1366 char *errstring;
1367 struct disklabel *lp = cs->sc_dkdev.dk_label;
1368 struct cpu_disklabel *clp = cs->sc_dkdev.dk_cpulabel;
1369 struct ccdgeom *ccg = &cs->sc_geom;
1370
1371 bzero(lp, sizeof(*lp));
1372 bzero(clp, sizeof(*clp));
1373
1374 lp->d_secperunit = cs->sc_size;
1375 lp->d_secsize = ccg->ccg_secsize;
1376 lp->d_nsectors = ccg->ccg_nsectors;
1377 lp->d_ntracks = ccg->ccg_ntracks;
1378 lp->d_ncylinders = ccg->ccg_ncylinders;
1379 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1380
1381 strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename));
1382 lp->d_type = DTYPE_CCD;
1383 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
1384 lp->d_rpm = 3600;
1385 lp->d_interleave = 1;
1386 lp->d_flags = 0;
1387
1388 lp->d_partitions[RAW_PART].p_offset = 0;
1389 lp->d_partitions[RAW_PART].p_size = cs->sc_size;
1390 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
1391 lp->d_npartitions = RAW_PART + 1;
1392
1393 lp->d_magic = DISKMAGIC;
1394 lp->d_magic2 = DISKMAGIC;
1395 lp->d_checksum = dkcksum(cs->sc_dkdev.dk_label);
1396
1397 /*
1398 * Call the generic disklabel extraction routine.
1399 */
1400 errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy,
1401 cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel);
1402 if (errstring)
1403 ccdmakedisklabel(cs);
1404
1405 #ifdef DEBUG
1406 /* It's actually extremely common to have unlabeled ccds. */
1407 if (ccddebug & CCDB_LABEL)
1408 if (errstring != NULL)
1409 printf("%s: %s\n", cs->sc_xname, errstring);
1410 #endif
1411 }
1412
1413 /*
1414 * Take care of things one might want to take care of in the event
1415 * that a disklabel isn't present.
1416 */
1417 static void
1418 ccdmakedisklabel(cs)
1419 struct ccd_softc *cs;
1420 {
1421 struct disklabel *lp = cs->sc_dkdev.dk_label;
1422
1423 /*
1424 * For historical reasons, if there's no disklabel present
1425 * the raw partition must be marked FS_BSDFFS.
1426 */
1427 lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS;
1428
1429 strncpy(lp->d_packname, "default label", sizeof(lp->d_packname));
1430 }
1431
1432 /*
1433 * Wait interruptibly for an exclusive lock.
1434 *
1435 * XXX
1436 * Several drivers do this; it should be abstracted and made MP-safe.
1437 */
1438 static int
1439 ccdlock(cs)
1440 struct ccd_softc *cs;
1441 {
1442 int error;
1443
1444 while ((cs->sc_flags & CCDF_LOCKED) != 0) {
1445 cs->sc_flags |= CCDF_WANTED;
1446 if ((error = tsleep(cs, PRIBIO | PCATCH, "ccdlck", 0)) != 0)
1447 return (error);
1448 }
1449 cs->sc_flags |= CCDF_LOCKED;
1450 return (0);
1451 }
1452
1453 /*
1454 * Unlock and wake up any waiters.
1455 */
1456 static void
1457 ccdunlock(cs)
1458 struct ccd_softc *cs;
1459 {
1460
1461 cs->sc_flags &= ~CCDF_LOCKED;
1462 if ((cs->sc_flags & CCDF_WANTED) != 0) {
1463 cs->sc_flags &= ~CCDF_WANTED;
1464 wakeup(cs);
1465 }
1466 }
1467
1468 #ifdef DEBUG
1469 static void
1470 printiinfo(ii)
1471 struct ccdiinfo *ii;
1472 {
1473 register int ix, i;
1474
1475 for (ix = 0; ii->ii_ndisk; ix++, ii++) {
1476 printf(" itab[%d]: #dk %d sblk %d soff %d",
1477 ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
1478 for (i = 0; i < ii->ii_ndisk; i++)
1479 printf(" %d", ii->ii_index[i]);
1480 printf("\n");
1481 }
1482 }
1483 #endif
1484