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