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