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