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