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