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