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