1 /* $NetBSD: ccd.c,v 1.162 2015/01/02 19:42:06 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998, 1999, 2007, 2009 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, and by Andrew Doran. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1988 University of Utah. 34 * Copyright (c) 1990, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * from: Utah $Hdr: cd.c 1.6 90/11/28$ 66 * 67 * @(#)cd.c 8.2 (Berkeley) 11/16/93 68 */ 69 70 /* 71 * "Concatenated" disk driver. 72 * 73 * Notes on concurrency: 74 * 75 * => sc_dvlock serializes access to the device nodes, excluding block I/O. 76 * 77 * => sc_iolock serializes access to (sc_flags & CCDF_INITED), disk stats, 78 * sc_stop, sc_bufq and b_resid from master buffers. 79 * 80 * => a combination of CCDF_INITED, sc_inflight, and sc_iolock is used to 81 * serialize I/O and configuration changes. 82 * 83 * => the in-core disk label does not change while the device is open. 84 * 85 * On memory consumption: ccd fans out I/O requests and so needs to 86 * allocate memory. If the system is desperately low on memory, we 87 * single thread I/O. 88 */ 89 90 #include <sys/cdefs.h> 91 __KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.162 2015/01/02 19:42:06 christos Exp $"); 92 93 #if defined(_KERNEL_OPT) 94 #include "opt_compat_netbsd.h" 95 #endif 96 97 #include <sys/param.h> 98 #include <sys/systm.h> 99 #include <sys/kernel.h> 100 #include <sys/proc.h> 101 #include <sys/errno.h> 102 #include <sys/buf.h> 103 #include <sys/kmem.h> 104 #include <sys/pool.h> 105 #include <sys/module.h> 106 #include <sys/namei.h> 107 #include <sys/stat.h> 108 #include <sys/ioctl.h> 109 #include <sys/disklabel.h> 110 #include <sys/device.h> 111 #include <sys/disk.h> 112 #include <sys/syslog.h> 113 #include <sys/fcntl.h> 114 #include <sys/vnode.h> 115 #include <sys/conf.h> 116 #include <sys/mutex.h> 117 #include <sys/queue.h> 118 #include <sys/kauth.h> 119 #include <sys/kthread.h> 120 #include <sys/bufq.h> 121 #include <sys/sysctl.h> 122 123 #include <uvm/uvm_extern.h> 124 125 #include <dev/ccdvar.h> 126 #include <dev/dkvar.h> 127 128 #include <miscfs/specfs/specdev.h> /* for v_rdev */ 129 130 #if defined(CCDDEBUG) && !defined(DEBUG) 131 #define DEBUG 132 #endif 133 134 #ifdef DEBUG 135 #define CCDB_FOLLOW 0x01 136 #define CCDB_INIT 0x02 137 #define CCDB_IO 0x04 138 #define CCDB_LABEL 0x08 139 #define CCDB_VNODE 0x10 140 int ccddebug = 0x00; 141 #endif 142 143 #define ccdunit(x) DISKUNIT(x) 144 145 struct ccdbuf { 146 struct buf cb_buf; /* new I/O buf */ 147 struct buf *cb_obp; /* ptr. to original I/O buf */ 148 struct ccd_softc *cb_sc; /* pointer to ccd softc */ 149 int cb_comp; /* target component */ 150 SIMPLEQ_ENTRY(ccdbuf) cb_q; /* fifo of component buffers */ 151 }; 152 153 /* component buffer pool */ 154 static pool_cache_t ccd_cache; 155 156 #define CCD_GETBUF() pool_cache_get(ccd_cache, PR_WAITOK) 157 #define CCD_PUTBUF(cbp) pool_cache_put(ccd_cache, cbp) 158 159 #define CCDLABELDEV(dev) \ 160 (MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART)) 161 162 /* called by main() at boot time */ 163 void ccdattach(int); 164 void ccddetach(void); 165 166 /* called by biodone() at interrupt time */ 167 static void ccdiodone(struct buf *); 168 169 static void ccdinterleave(struct ccd_softc *); 170 static int ccdinit(struct ccd_softc *, char **, struct vnode **, 171 struct lwp *); 172 static struct ccdbuf *ccdbuffer(struct ccd_softc *, struct buf *, 173 daddr_t, void *, long); 174 static void ccdgetdefaultlabel(struct ccd_softc *, struct disklabel *); 175 static void ccdgetdisklabel(dev_t); 176 static void ccdmakedisklabel(struct ccd_softc *); 177 static void ccdstart(struct ccd_softc *); 178 static void ccdthread(void *); 179 180 static dev_type_open(ccdopen); 181 static dev_type_close(ccdclose); 182 static dev_type_read(ccdread); 183 static dev_type_write(ccdwrite); 184 static dev_type_ioctl(ccdioctl); 185 static dev_type_strategy(ccdstrategy); 186 static dev_type_size(ccdsize); 187 188 const struct bdevsw ccd_bdevsw = { 189 .d_open = ccdopen, 190 .d_close = ccdclose, 191 .d_strategy = ccdstrategy, 192 .d_ioctl = ccdioctl, 193 .d_dump = nodump, 194 .d_psize = ccdsize, 195 .d_discard = nodiscard, 196 .d_flag = D_DISK | D_MPSAFE 197 }; 198 199 const struct cdevsw ccd_cdevsw = { 200 .d_open = ccdopen, 201 .d_close = ccdclose, 202 .d_read = ccdread, 203 .d_write = ccdwrite, 204 .d_ioctl = ccdioctl, 205 .d_stop = nostop, 206 .d_tty = notty, 207 .d_poll = nopoll, 208 .d_mmap = nommap, 209 .d_kqfilter = nokqfilter, 210 .d_discard = nodiscard, 211 .d_flag = D_DISK | D_MPSAFE 212 }; 213 214 #ifdef DEBUG 215 static void printiinfo(struct ccdiinfo *); 216 #endif 217 218 static LIST_HEAD(, ccd_softc) ccds = LIST_HEAD_INITIALIZER(ccds); 219 static kmutex_t ccd_lock; 220 static size_t ccd_nactive = 0; 221 222 static struct ccd_softc * 223 ccdcreate(int unit) { 224 struct ccd_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); 225 if (sc == NULL) { 226 #ifdef DIAGNOSTIC 227 printf("%s: out of memory\n", __func__); 228 #endif 229 return NULL; 230 } 231 /* Initialize per-softc structures. */ 232 snprintf(sc->sc_xname, sizeof(sc->sc_xname), "ccd%d", unit); 233 mutex_init(&sc->sc_dvlock, MUTEX_DEFAULT, IPL_NONE); 234 sc->sc_iolock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 235 cv_init(&sc->sc_stop, "ccdstop"); 236 cv_init(&sc->sc_push, "ccdthr"); 237 disk_init(&sc->sc_dkdev, sc->sc_xname, NULL); /* XXX */ 238 return sc; 239 } 240 241 static void 242 ccddestroy(struct ccd_softc *sc) { 243 mutex_obj_free(sc->sc_iolock); 244 mutex_exit(&sc->sc_dvlock); 245 mutex_destroy(&sc->sc_dvlock); 246 cv_destroy(&sc->sc_stop); 247 cv_destroy(&sc->sc_push); 248 disk_destroy(&sc->sc_dkdev); 249 kmem_free(sc, sizeof(*sc)); 250 } 251 252 static struct ccd_softc * 253 ccdget(int unit, int make) { 254 struct ccd_softc *sc; 255 if (unit < 0) { 256 #ifdef DIAGNOSTIC 257 panic("%s: unit %d!", __func__, unit); 258 #endif 259 return NULL; 260 } 261 mutex_enter(&ccd_lock); 262 LIST_FOREACH(sc, &ccds, sc_link) { 263 if (sc->sc_unit == unit) { 264 mutex_exit(&ccd_lock); 265 return sc; 266 } 267 } 268 mutex_exit(&ccd_lock); 269 if (!make) 270 return NULL; 271 if ((sc = ccdcreate(unit)) == NULL) 272 return NULL; 273 mutex_enter(&ccd_lock); 274 LIST_INSERT_HEAD(&ccds, sc, sc_link); 275 ccd_nactive++; 276 mutex_exit(&ccd_lock); 277 return sc; 278 } 279 280 static void 281 ccdput(struct ccd_softc *sc) { 282 mutex_enter(&ccd_lock); 283 LIST_REMOVE(sc, sc_link); 284 ccd_nactive--; 285 mutex_exit(&ccd_lock); 286 ccddestroy(sc); 287 } 288 289 /* 290 * Called by main() during pseudo-device attachment. All we need 291 * to do is allocate enough space for devices to be configured later. 292 */ 293 void 294 ccdattach(int num) 295 { 296 mutex_init(&ccd_lock, MUTEX_DEFAULT, IPL_NONE); 297 298 /* Initialize the component buffer pool. */ 299 ccd_cache = pool_cache_init(sizeof(struct ccdbuf), 0, 300 0, 0, "ccdbuf", NULL, IPL_BIO, NULL, NULL, NULL); 301 } 302 303 void 304 ccddetach(void) 305 { 306 pool_cache_destroy(ccd_cache); 307 mutex_destroy(&ccd_lock); 308 } 309 310 static int 311 ccdinit(struct ccd_softc *cs, char **cpaths, struct vnode **vpp, 312 struct lwp *l) 313 { 314 struct ccdcinfo *ci = NULL; 315 int ix; 316 struct ccdgeom *ccg = &cs->sc_geom; 317 char *tmppath; 318 int error, path_alloced; 319 uint64_t psize, minsize; 320 unsigned secsize, maxsecsize; 321 struct disk_geom *dg; 322 323 #ifdef DEBUG 324 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 325 printf("%s: ccdinit\n", cs->sc_xname); 326 #endif 327 328 /* Allocate space for the component info. */ 329 cs->sc_cinfo = kmem_alloc(cs->sc_nccdisks * sizeof(*cs->sc_cinfo), 330 KM_SLEEP); 331 tmppath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 332 333 cs->sc_size = 0; 334 335 /* 336 * Verify that each component piece exists and record 337 * relevant information about it. 338 */ 339 maxsecsize = 0; 340 minsize = 0; 341 for (ix = 0, path_alloced = 0; ix < cs->sc_nccdisks; ix++) { 342 ci = &cs->sc_cinfo[ix]; 343 ci->ci_vp = vpp[ix]; 344 345 /* 346 * Copy in the pathname of the component. 347 */ 348 memset(tmppath, 0, MAXPATHLEN); /* sanity */ 349 error = copyinstr(cpaths[ix], tmppath, 350 MAXPATHLEN, &ci->ci_pathlen); 351 if (ci->ci_pathlen == 0) 352 error = EINVAL; 353 if (error) { 354 #ifdef DEBUG 355 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 356 printf("%s: can't copy path, error = %d\n", 357 cs->sc_xname, error); 358 #endif 359 goto out; 360 } 361 ci->ci_path = kmem_alloc(ci->ci_pathlen, KM_SLEEP); 362 memcpy(ci->ci_path, tmppath, ci->ci_pathlen); 363 path_alloced++; 364 365 /* 366 * XXX: Cache the component's dev_t. 367 */ 368 ci->ci_dev = vpp[ix]->v_rdev; 369 370 /* 371 * Get partition information for the component. 372 */ 373 error = getdisksize(vpp[ix], &psize, &secsize); 374 if (error) { 375 #ifdef DEBUG 376 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 377 printf("%s: %s: disksize failed, error = %d\n", 378 cs->sc_xname, ci->ci_path, error); 379 #endif 380 goto out; 381 } 382 383 /* 384 * Calculate the size, truncating to an interleave 385 * boundary if necessary. 386 */ 387 maxsecsize = secsize > maxsecsize ? secsize : maxsecsize; 388 if (cs->sc_ileave > 1) 389 psize -= psize % cs->sc_ileave; 390 391 if (psize == 0) { 392 #ifdef DEBUG 393 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 394 printf("%s: %s: size == 0\n", 395 cs->sc_xname, ci->ci_path); 396 #endif 397 error = ENODEV; 398 goto out; 399 } 400 401 if (minsize == 0 || psize < minsize) 402 minsize = psize; 403 ci->ci_size = psize; 404 cs->sc_size += psize; 405 } 406 407 /* 408 * Don't allow the interleave to be smaller than 409 * the biggest component sector. 410 */ 411 if ((cs->sc_ileave > 0) && 412 (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { 413 #ifdef DEBUG 414 if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 415 printf("%s: interleave must be at least %d\n", 416 cs->sc_xname, (maxsecsize / DEV_BSIZE)); 417 #endif 418 error = EINVAL; 419 goto out; 420 } 421 422 /* 423 * If uniform interleave is desired set all sizes to that of 424 * the smallest component. 425 */ 426 if (cs->sc_flags & CCDF_UNIFORM) { 427 for (ci = cs->sc_cinfo; 428 ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 429 ci->ci_size = minsize; 430 431 cs->sc_size = cs->sc_nccdisks * minsize; 432 } 433 434 /* 435 * Construct the interleave table. 436 */ 437 ccdinterleave(cs); 438 439 /* 440 * Create pseudo-geometry based on 1MB cylinders. It's 441 * pretty close. 442 */ 443 ccg->ccg_secsize = DEV_BSIZE; 444 ccg->ccg_ntracks = 1; 445 ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize); 446 ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors; 447 448 dg = &cs->sc_dkdev.dk_geom; 449 memset(dg, 0, sizeof(*dg)); 450 dg->dg_secperunit = cs->sc_size; 451 dg->dg_secsize = ccg->ccg_secsize; 452 dg->dg_nsectors = ccg->ccg_nsectors; 453 dg->dg_ntracks = ccg->ccg_ntracks; 454 dg->dg_ncylinders = ccg->ccg_ncylinders; 455 456 if (cs->sc_ileave > 0) 457 aprint_normal("%s: Interleaving %d component%s " 458 "(%d block interleave)\n", cs->sc_xname, 459 cs->sc_nccdisks, (cs->sc_nccdisks != 0 ? "s" : ""), 460 cs->sc_ileave); 461 else 462 aprint_normal("%s: Concatenating %d component%s\n", 463 cs->sc_xname, 464 cs->sc_nccdisks, (cs->sc_nccdisks != 0 ? "s" : "")); 465 for (ix = 0; ix < cs->sc_nccdisks; ix++) { 466 ci = &cs->sc_cinfo[ix]; 467 aprint_normal("%s: %s (%ju blocks)\n", cs->sc_xname, 468 ci->ci_path, (uintmax_t)ci->ci_size); 469 } 470 aprint_normal("%s: total %ju blocks\n", cs->sc_xname, cs->sc_size); 471 472 /* 473 * Create thread to handle deferred I/O. 474 */ 475 cs->sc_zap = false; 476 error = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, ccdthread, 477 cs, &cs->sc_thread, "%s", cs->sc_xname); 478 if (error) { 479 printf("ccdinit: can't create thread: %d\n", error); 480 goto out; 481 } 482 483 /* 484 * Only now that everything is set up can we enable the device. 485 */ 486 mutex_enter(cs->sc_iolock); 487 cs->sc_flags |= CCDF_INITED; 488 mutex_exit(cs->sc_iolock); 489 kmem_free(tmppath, MAXPATHLEN); 490 return (0); 491 492 out: 493 for (ix = 0; ix < path_alloced; ix++) { 494 kmem_free(cs->sc_cinfo[ix].ci_path, 495 cs->sc_cinfo[ix].ci_pathlen); 496 } 497 kmem_free(cs->sc_cinfo, cs->sc_nccdisks * sizeof(struct ccdcinfo)); 498 kmem_free(tmppath, MAXPATHLEN); 499 return (error); 500 } 501 502 static void 503 ccdinterleave(struct ccd_softc *cs) 504 { 505 struct ccdcinfo *ci, *smallci; 506 struct ccdiinfo *ii; 507 daddr_t bn, lbn; 508 int ix; 509 u_long size; 510 511 #ifdef DEBUG 512 if (ccddebug & CCDB_INIT) 513 printf("ccdinterleave(%p): ileave %d\n", cs, cs->sc_ileave); 514 #endif 515 /* 516 * Allocate an interleave table. 517 * Chances are this is too big, but we don't care. 518 */ 519 size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo); 520 cs->sc_itable = kmem_zalloc(size, KM_SLEEP); 521 522 /* 523 * Trivial case: no interleave (actually interleave of disk size). 524 * Each table entry represents a single component in its entirety. 525 */ 526 if (cs->sc_ileave == 0) { 527 bn = 0; 528 ii = cs->sc_itable; 529 530 for (ix = 0; ix < cs->sc_nccdisks; ix++) { 531 /* Allocate space for ii_index. */ 532 ii->ii_indexsz = sizeof(int); 533 ii->ii_index = kmem_alloc(ii->ii_indexsz, KM_SLEEP); 534 ii->ii_ndisk = 1; 535 ii->ii_startblk = bn; 536 ii->ii_startoff = 0; 537 ii->ii_index[0] = ix; 538 bn += cs->sc_cinfo[ix].ci_size; 539 ii++; 540 } 541 ii->ii_ndisk = 0; 542 #ifdef DEBUG 543 if (ccddebug & CCDB_INIT) 544 printiinfo(cs->sc_itable); 545 #endif 546 return; 547 } 548 549 /* 550 * The following isn't fast or pretty; it doesn't have to be. 551 */ 552 size = 0; 553 bn = lbn = 0; 554 for (ii = cs->sc_itable; ; ii++) { 555 /* Allocate space for ii_index. */ 556 ii->ii_indexsz = sizeof(int) * cs->sc_nccdisks; 557 ii->ii_index = kmem_alloc(ii->ii_indexsz, KM_SLEEP); 558 559 /* 560 * Locate the smallest of the remaining components 561 */ 562 smallci = NULL; 563 for (ci = cs->sc_cinfo; 564 ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 565 if (ci->ci_size > size && 566 (smallci == NULL || 567 ci->ci_size < smallci->ci_size)) 568 smallci = ci; 569 570 /* 571 * Nobody left, all done 572 */ 573 if (smallci == NULL) { 574 ii->ii_ndisk = 0; 575 break; 576 } 577 578 /* 579 * Record starting logical block and component offset 580 */ 581 ii->ii_startblk = bn / cs->sc_ileave; 582 ii->ii_startoff = lbn; 583 584 /* 585 * Determine how many disks take part in this interleave 586 * and record their indices. 587 */ 588 ix = 0; 589 for (ci = cs->sc_cinfo; 590 ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 591 if (ci->ci_size >= smallci->ci_size) 592 ii->ii_index[ix++] = ci - cs->sc_cinfo; 593 ii->ii_ndisk = ix; 594 bn += ix * (smallci->ci_size - size); 595 lbn = smallci->ci_size / cs->sc_ileave; 596 size = smallci->ci_size; 597 } 598 #ifdef DEBUG 599 if (ccddebug & CCDB_INIT) 600 printiinfo(cs->sc_itable); 601 #endif 602 } 603 604 /* ARGSUSED */ 605 static int 606 ccdopen(dev_t dev, int flags, int fmt, struct lwp *l) 607 { 608 int unit = ccdunit(dev); 609 struct ccd_softc *cs; 610 struct disklabel *lp; 611 int error = 0, part, pmask; 612 613 #ifdef DEBUG 614 if (ccddebug & CCDB_FOLLOW) 615 printf("ccdopen(0x%"PRIx64", 0x%x)\n", dev, flags); 616 #endif 617 if ((cs = ccdget(unit, 1)) == NULL) 618 return ENXIO; 619 620 mutex_enter(&cs->sc_dvlock); 621 622 lp = cs->sc_dkdev.dk_label; 623 624 part = DISKPART(dev); 625 pmask = (1 << part); 626 627 /* 628 * If we're initialized, check to see if there are any other 629 * open partitions. If not, then it's safe to update 630 * the in-core disklabel. Only read the disklabel if it is 631 * not already valid. 632 */ 633 if ((cs->sc_flags & (CCDF_INITED|CCDF_VLABEL)) == CCDF_INITED && 634 cs->sc_dkdev.dk_openmask == 0) 635 ccdgetdisklabel(dev); 636 637 /* Check that the partition exists. */ 638 if (part != RAW_PART) { 639 if (((cs->sc_flags & CCDF_INITED) == 0) || 640 ((part >= lp->d_npartitions) || 641 (lp->d_partitions[part].p_fstype == FS_UNUSED))) { 642 error = ENXIO; 643 goto done; 644 } 645 } 646 647 /* Prevent our unit from being unconfigured while open. */ 648 switch (fmt) { 649 case S_IFCHR: 650 cs->sc_dkdev.dk_copenmask |= pmask; 651 break; 652 653 case S_IFBLK: 654 cs->sc_dkdev.dk_bopenmask |= pmask; 655 break; 656 } 657 cs->sc_dkdev.dk_openmask = 658 cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 659 660 done: 661 mutex_exit(&cs->sc_dvlock); 662 return (error); 663 } 664 665 /* ARGSUSED */ 666 static int 667 ccdclose(dev_t dev, int flags, int fmt, struct lwp *l) 668 { 669 int unit = ccdunit(dev); 670 struct ccd_softc *cs; 671 int part; 672 673 #ifdef DEBUG 674 if (ccddebug & CCDB_FOLLOW) 675 printf("ccdclose(0x%"PRIx64", 0x%x)\n", dev, flags); 676 #endif 677 678 if ((cs = ccdget(unit, 0)) == NULL) 679 return ENXIO; 680 681 mutex_enter(&cs->sc_dvlock); 682 683 part = DISKPART(dev); 684 685 /* ...that much closer to allowing unconfiguration... */ 686 switch (fmt) { 687 case S_IFCHR: 688 cs->sc_dkdev.dk_copenmask &= ~(1 << part); 689 break; 690 691 case S_IFBLK: 692 cs->sc_dkdev.dk_bopenmask &= ~(1 << part); 693 break; 694 } 695 cs->sc_dkdev.dk_openmask = 696 cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 697 698 if (cs->sc_dkdev.dk_openmask == 0) { 699 if ((cs->sc_flags & CCDF_KLABEL) == 0) 700 cs->sc_flags &= ~CCDF_VLABEL; 701 } 702 703 mutex_exit(&cs->sc_dvlock); 704 return (0); 705 } 706 707 static bool 708 ccdbackoff(struct ccd_softc *cs) 709 { 710 711 /* XXX Arbitrary, should be a uvm call. */ 712 return uvmexp.free < (uvmexp.freemin >> 1) && 713 disk_isbusy(&cs->sc_dkdev); 714 } 715 716 static void 717 ccdthread(void *cookie) 718 { 719 struct ccd_softc *cs; 720 721 cs = cookie; 722 723 #ifdef DEBUG 724 if (ccddebug & CCDB_FOLLOW) 725 printf("ccdthread: hello\n"); 726 #endif 727 728 mutex_enter(cs->sc_iolock); 729 while (__predict_true(!cs->sc_zap)) { 730 if (bufq_peek(cs->sc_bufq) == NULL) { 731 /* Nothing to do. */ 732 cv_wait(&cs->sc_push, cs->sc_iolock); 733 continue; 734 } 735 if (ccdbackoff(cs)) { 736 /* Wait for memory to become available. */ 737 (void)cv_timedwait(&cs->sc_push, cs->sc_iolock, 1); 738 continue; 739 } 740 #ifdef DEBUG 741 if (ccddebug & CCDB_FOLLOW) 742 printf("ccdthread: dispatching I/O\n"); 743 #endif 744 ccdstart(cs); 745 mutex_enter(cs->sc_iolock); 746 } 747 cs->sc_thread = NULL; 748 mutex_exit(cs->sc_iolock); 749 #ifdef DEBUG 750 if (ccddebug & CCDB_FOLLOW) 751 printf("ccdthread: goodbye\n"); 752 #endif 753 kthread_exit(0); 754 } 755 756 static void 757 ccdstrategy(struct buf *bp) 758 { 759 int unit = ccdunit(bp->b_dev); 760 struct ccd_softc *cs; 761 if ((cs = ccdget(unit, 0)) == NULL) 762 return; 763 764 /* Must be open or reading label. */ 765 KASSERT(cs->sc_dkdev.dk_openmask != 0 || 766 (cs->sc_flags & CCDF_RLABEL) != 0); 767 768 mutex_enter(cs->sc_iolock); 769 /* Synchronize with device init/uninit. */ 770 if (__predict_false((cs->sc_flags & CCDF_INITED) == 0)) { 771 mutex_exit(cs->sc_iolock); 772 #ifdef DEBUG 773 if (ccddebug & CCDB_FOLLOW) 774 printf("ccdstrategy: unit %d: not inited\n", unit); 775 #endif 776 bp->b_error = ENXIO; 777 bp->b_resid = bp->b_bcount; 778 biodone(bp); 779 return; 780 } 781 782 /* Defer to thread if system is low on memory. */ 783 bufq_put(cs->sc_bufq, bp); 784 if (__predict_false(ccdbackoff(cs))) { 785 mutex_exit(cs->sc_iolock); 786 #ifdef DEBUG 787 if (ccddebug & CCDB_FOLLOW) 788 printf("ccdstrategy: holding off on I/O\n"); 789 #endif 790 return; 791 } 792 ccdstart(cs); 793 } 794 795 static void 796 ccdstart(struct ccd_softc *cs) 797 { 798 daddr_t blkno; 799 int wlabel; 800 struct disklabel *lp; 801 long bcount, rcount; 802 struct ccdbuf *cbp; 803 char *addr; 804 daddr_t bn; 805 vnode_t *vp; 806 buf_t *bp; 807 808 KASSERT(mutex_owned(cs->sc_iolock)); 809 810 disk_busy(&cs->sc_dkdev); 811 bp = bufq_get(cs->sc_bufq); 812 KASSERT(bp != NULL); 813 814 #ifdef DEBUG 815 if (ccddebug & CCDB_FOLLOW) 816 printf("ccdstart(%s, %p)\n", cs->sc_xname, bp); 817 #endif 818 819 /* If it's a nil transfer, wake up the top half now. */ 820 if (bp->b_bcount == 0) 821 goto done; 822 823 lp = cs->sc_dkdev.dk_label; 824 825 /* 826 * Do bounds checking and adjust transfer. If there's an 827 * error, the bounds check will flag that for us. Convert 828 * the partition relative block number to an absolute. 829 */ 830 blkno = bp->b_blkno; 831 wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); 832 if (DISKPART(bp->b_dev) != RAW_PART) { 833 if (bounds_check_with_label(&cs->sc_dkdev, bp, wlabel) <= 0) 834 goto done; 835 blkno += lp->d_partitions[DISKPART(bp->b_dev)].p_offset; 836 } 837 mutex_exit(cs->sc_iolock); 838 bp->b_rawblkno = blkno; 839 840 /* Allocate the component buffers and start I/O! */ 841 bp->b_resid = bp->b_bcount; 842 bn = bp->b_rawblkno; 843 addr = bp->b_data; 844 for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { 845 cbp = ccdbuffer(cs, bp, bn, addr, bcount); 846 rcount = cbp->cb_buf.b_bcount; 847 bn += btodb(rcount); 848 addr += rcount; 849 vp = cbp->cb_buf.b_vp; 850 if ((cbp->cb_buf.b_flags & B_READ) == 0) { 851 mutex_enter(vp->v_interlock); 852 vp->v_numoutput++; 853 mutex_exit(vp->v_interlock); 854 } 855 (void)VOP_STRATEGY(vp, &cbp->cb_buf); 856 } 857 return; 858 859 done: 860 disk_unbusy(&cs->sc_dkdev, 0, 0); 861 cv_broadcast(&cs->sc_stop); 862 cv_broadcast(&cs->sc_push); 863 mutex_exit(cs->sc_iolock); 864 bp->b_resid = bp->b_bcount; 865 biodone(bp); 866 } 867 868 /* 869 * Build a component buffer header. 870 */ 871 static struct ccdbuf * 872 ccdbuffer(struct ccd_softc *cs, struct buf *bp, daddr_t bn, void *addr, 873 long bcount) 874 { 875 struct ccdcinfo *ci; 876 struct ccdbuf *cbp; 877 daddr_t cbn, cboff; 878 u_int64_t cbc; 879 int ccdisk; 880 881 #ifdef DEBUG 882 if (ccddebug & CCDB_IO) 883 printf("ccdbuffer(%p, %p, %" PRId64 ", %p, %ld)\n", 884 cs, bp, bn, addr, bcount); 885 #endif 886 /* 887 * Determine which component bn falls in. 888 */ 889 cbn = bn; 890 cboff = 0; 891 892 /* 893 * Serially concatenated 894 */ 895 if (cs->sc_ileave == 0) { 896 daddr_t sblk; 897 898 sblk = 0; 899 for (ccdisk = 0, ci = &cs->sc_cinfo[ccdisk]; 900 cbn >= sblk + ci->ci_size; 901 ccdisk++, ci = &cs->sc_cinfo[ccdisk]) 902 sblk += ci->ci_size; 903 cbn -= sblk; 904 } 905 /* 906 * Interleaved 907 */ 908 else { 909 struct ccdiinfo *ii; 910 int off; 911 912 cboff = cbn % cs->sc_ileave; 913 cbn /= cs->sc_ileave; 914 for (ii = cs->sc_itable; ii->ii_ndisk; ii++) 915 if (ii->ii_startblk > cbn) 916 break; 917 ii--; 918 off = cbn - ii->ii_startblk; 919 if (ii->ii_ndisk == 1) { 920 ccdisk = ii->ii_index[0]; 921 cbn = ii->ii_startoff + off; 922 } else { 923 ccdisk = ii->ii_index[off % ii->ii_ndisk]; 924 cbn = ii->ii_startoff + off / ii->ii_ndisk; 925 } 926 cbn *= cs->sc_ileave; 927 ci = &cs->sc_cinfo[ccdisk]; 928 } 929 930 /* 931 * Fill in the component buf structure. 932 */ 933 cbp = CCD_GETBUF(); 934 KASSERT(cbp != NULL); 935 buf_init(&cbp->cb_buf); 936 cbp->cb_buf.b_flags = bp->b_flags; 937 cbp->cb_buf.b_oflags = bp->b_oflags; 938 cbp->cb_buf.b_cflags = bp->b_cflags; 939 cbp->cb_buf.b_iodone = ccdiodone; 940 cbp->cb_buf.b_proc = bp->b_proc; 941 cbp->cb_buf.b_dev = ci->ci_dev; 942 cbp->cb_buf.b_blkno = cbn + cboff; 943 cbp->cb_buf.b_data = addr; 944 cbp->cb_buf.b_vp = ci->ci_vp; 945 cbp->cb_buf.b_objlock = ci->ci_vp->v_interlock; 946 if (cs->sc_ileave == 0) 947 cbc = dbtob((u_int64_t)(ci->ci_size - cbn)); 948 else 949 cbc = dbtob((u_int64_t)(cs->sc_ileave - cboff)); 950 cbp->cb_buf.b_bcount = cbc < bcount ? cbc : bcount; 951 952 /* 953 * context for ccdiodone 954 */ 955 cbp->cb_obp = bp; 956 cbp->cb_sc = cs; 957 cbp->cb_comp = ccdisk; 958 959 BIO_COPYPRIO(&cbp->cb_buf, bp); 960 961 #ifdef DEBUG 962 if (ccddebug & CCDB_IO) 963 printf(" dev 0x%"PRIx64"(u%lu): cbp %p bn %" PRId64 " addr %p" 964 " bcnt %d\n", 965 ci->ci_dev, (unsigned long) (ci-cs->sc_cinfo), cbp, 966 cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, 967 cbp->cb_buf.b_bcount); 968 #endif 969 970 return (cbp); 971 } 972 973 /* 974 * Called at interrupt time. 975 * Mark the component as done and if all components are done, 976 * take a ccd interrupt. 977 */ 978 static void 979 ccdiodone(struct buf *vbp) 980 { 981 struct ccdbuf *cbp = (struct ccdbuf *) vbp; 982 struct buf *bp = cbp->cb_obp; 983 struct ccd_softc *cs = cbp->cb_sc; 984 int count; 985 986 #ifdef DEBUG 987 if (ccddebug & CCDB_FOLLOW) 988 printf("ccdiodone(%p)\n", cbp); 989 if (ccddebug & CCDB_IO) { 990 printf("ccdiodone: bp %p bcount %d resid %d\n", 991 bp, bp->b_bcount, bp->b_resid); 992 printf(" dev 0x%"PRIx64"(u%d), cbp %p bn %" PRId64 " addr %p" 993 " bcnt %d\n", 994 cbp->cb_buf.b_dev, cbp->cb_comp, cbp, 995 cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, 996 cbp->cb_buf.b_bcount); 997 } 998 #endif 999 1000 if (cbp->cb_buf.b_error != 0) { 1001 bp->b_error = cbp->cb_buf.b_error; 1002 printf("%s: error %d on component %d\n", 1003 cs->sc_xname, bp->b_error, cbp->cb_comp); 1004 } 1005 count = cbp->cb_buf.b_bcount; 1006 buf_destroy(&cbp->cb_buf); 1007 CCD_PUTBUF(cbp); 1008 1009 /* 1010 * If all done, "interrupt". 1011 */ 1012 mutex_enter(cs->sc_iolock); 1013 bp->b_resid -= count; 1014 if (bp->b_resid < 0) 1015 panic("ccdiodone: count"); 1016 if (bp->b_resid == 0) { 1017 /* 1018 * Request is done for better or worse, wakeup the top half. 1019 */ 1020 if (bp->b_error != 0) 1021 bp->b_resid = bp->b_bcount; 1022 disk_unbusy(&cs->sc_dkdev, (bp->b_bcount - bp->b_resid), 1023 (bp->b_flags & B_READ)); 1024 if (!disk_isbusy(&cs->sc_dkdev)) { 1025 if (bufq_peek(cs->sc_bufq) != NULL) { 1026 cv_broadcast(&cs->sc_push); 1027 } 1028 cv_broadcast(&cs->sc_stop); 1029 } 1030 mutex_exit(cs->sc_iolock); 1031 biodone(bp); 1032 } else 1033 mutex_exit(cs->sc_iolock); 1034 } 1035 1036 /* ARGSUSED */ 1037 static int 1038 ccdread(dev_t dev, struct uio *uio, int flags) 1039 { 1040 int unit = ccdunit(dev); 1041 struct ccd_softc *cs; 1042 1043 #ifdef DEBUG 1044 if (ccddebug & CCDB_FOLLOW) 1045 printf("ccdread(0x%"PRIx64", %p)\n", dev, uio); 1046 #endif 1047 if ((cs = ccdget(unit, 0)) == NULL) 1048 return 0; 1049 1050 /* Unlocked advisory check, ccdstrategy check is synchronous. */ 1051 if ((cs->sc_flags & CCDF_INITED) == 0) 1052 return (ENXIO); 1053 1054 return (physio(ccdstrategy, NULL, dev, B_READ, minphys, uio)); 1055 } 1056 1057 /* ARGSUSED */ 1058 static int 1059 ccdwrite(dev_t dev, struct uio *uio, int flags) 1060 { 1061 int unit = ccdunit(dev); 1062 struct ccd_softc *cs; 1063 1064 #ifdef DEBUG 1065 if (ccddebug & CCDB_FOLLOW) 1066 printf("ccdwrite(0x%"PRIx64", %p)\n", dev, uio); 1067 #endif 1068 if ((cs = ccdget(unit, 0)) == NULL) 1069 return ENOENT; 1070 1071 /* Unlocked advisory check, ccdstrategy check is synchronous. */ 1072 if ((cs->sc_flags & CCDF_INITED) == 0) 1073 return (ENXIO); 1074 1075 return (physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio)); 1076 } 1077 1078 static int 1079 ccdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1080 { 1081 int unit = ccdunit(dev); 1082 int i, j, lookedup = 0, error = 0; 1083 int part, pmask, make; 1084 struct ccd_softc *cs; 1085 struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; 1086 kauth_cred_t uc; 1087 char **cpp; 1088 struct pathbuf *pb; 1089 struct vnode **vpp; 1090 #ifdef __HAVE_OLD_DISKLABEL 1091 struct disklabel newlabel; 1092 #endif 1093 1094 switch (cmd) { 1095 #if defined(COMPAT_60) && !defined(_LP64) 1096 case CCDIOCSET_60: 1097 #endif 1098 case CCDIOCSET: 1099 make = 1; 1100 break; 1101 default: 1102 make = 0; 1103 break; 1104 } 1105 1106 if ((cs = ccdget(unit, make)) == NULL) 1107 return ENOENT; 1108 uc = kauth_cred_get(); 1109 1110 /* 1111 * Compat code must not be called if on a platform where 1112 * sizeof (size_t) == sizeof (uint64_t) as CCDIOCSET will 1113 * be the same as CCDIOCSET_60 1114 */ 1115 #if defined(COMPAT_60) && !defined(_LP64) 1116 switch (cmd) { 1117 case CCDIOCSET_60: { 1118 struct ccd_ioctl ccionew; 1119 struct ccd_ioctl_60 *ccio60 = 1120 (struct ccd_ioctl_60 *)data; 1121 ccionew.ccio_disks = ccio->ccio_disks; 1122 ccionew.ccio_ndisks = ccio->ccio_ndisks; 1123 ccionew.ccio_ileave = ccio->ccio_ileave; 1124 ccionew.ccio_flags = ccio->ccio_flags; 1125 ccionew.ccio_unit = ccio->ccio_unit; 1126 error = ccdioctl(dev, CCDIOCSET, &ccionew, flag, l); 1127 if (!error) { 1128 /* Copy data back, adjust types if necessary */ 1129 ccio60->ccio_disks = ccionew.ccio_disks; 1130 ccio60->ccio_ndisks = ccionew.ccio_ndisks; 1131 ccio60->ccio_ileave = ccionew.ccio_ileave; 1132 ccio60->ccio_flags = ccionew.ccio_flags; 1133 ccio60->ccio_unit = ccionew.ccio_unit; 1134 ccio60->ccio_size = (size_t)ccionew.ccio_size; 1135 } 1136 return error; 1137 } 1138 break; 1139 1140 case CCDIOCCLR_60: 1141 /* 1142 * ccio_size member not used, so existing struct OK 1143 * drop through to existing non-compat version 1144 */ 1145 cmd = CCDIOCCLR; 1146 break; 1147 } 1148 #endif /* COMPAT_60 && !_LP64*/ 1149 1150 /* Must be open for writes for these commands... */ 1151 switch (cmd) { 1152 case CCDIOCSET: 1153 case CCDIOCCLR: 1154 case DIOCSDINFO: 1155 case DIOCWDINFO: 1156 case DIOCCACHESYNC: 1157 case DIOCAWEDGE: 1158 case DIOCDWEDGE: 1159 case DIOCMWEDGES: 1160 #ifdef __HAVE_OLD_DISKLABEL 1161 case ODIOCSDINFO: 1162 case ODIOCWDINFO: 1163 #endif 1164 case DIOCKLABEL: 1165 case DIOCWLABEL: 1166 if ((flag & FWRITE) == 0) 1167 return (EBADF); 1168 } 1169 1170 mutex_enter(&cs->sc_dvlock); 1171 1172 /* Must be initialized for these... */ 1173 switch (cmd) { 1174 case CCDIOCCLR: 1175 case DIOCGDINFO: 1176 case DIOCCACHESYNC: 1177 case DIOCAWEDGE: 1178 case DIOCDWEDGE: 1179 case DIOCLWEDGES: 1180 case DIOCMWEDGES: 1181 case DIOCSDINFO: 1182 case DIOCWDINFO: 1183 case DIOCGPART: 1184 case DIOCWLABEL: 1185 case DIOCKLABEL: 1186 case DIOCGDEFLABEL: 1187 #ifdef __HAVE_OLD_DISKLABEL 1188 case ODIOCGDINFO: 1189 case ODIOCSDINFO: 1190 case ODIOCWDINFO: 1191 case ODIOCGDEFLABEL: 1192 #endif 1193 if ((cs->sc_flags & CCDF_INITED) == 0) { 1194 error = ENXIO; 1195 goto out; 1196 } 1197 } 1198 1199 error = disk_ioctl(&cs->sc_dkdev, dev, cmd, data, flag, l); 1200 if (error != EPASSTHROUGH) 1201 goto out; 1202 1203 error = 0; 1204 switch (cmd) { 1205 case CCDIOCSET: 1206 if (cs->sc_flags & CCDF_INITED) { 1207 error = EBUSY; 1208 goto out; 1209 } 1210 1211 /* Validate the flags. */ 1212 if ((ccio->ccio_flags & CCDF_USERMASK) != ccio->ccio_flags) { 1213 error = EINVAL; 1214 goto out; 1215 } 1216 1217 if (ccio->ccio_ndisks > CCD_MAXNDISKS || 1218 ccio->ccio_ndisks == 0) { 1219 error = EINVAL; 1220 goto out; 1221 } 1222 1223 /* Fill in some important bits. */ 1224 cs->sc_ileave = ccio->ccio_ileave; 1225 cs->sc_nccdisks = ccio->ccio_ndisks; 1226 cs->sc_flags = ccio->ccio_flags & CCDF_USERMASK; 1227 1228 /* 1229 * Allocate space for and copy in the array of 1230 * component pathnames and device numbers. 1231 */ 1232 cpp = kmem_alloc(ccio->ccio_ndisks * sizeof(*cpp), KM_SLEEP); 1233 vpp = kmem_alloc(ccio->ccio_ndisks * sizeof(*vpp), KM_SLEEP); 1234 error = copyin(ccio->ccio_disks, cpp, 1235 ccio->ccio_ndisks * sizeof(*cpp)); 1236 if (error) { 1237 kmem_free(vpp, ccio->ccio_ndisks * sizeof(*vpp)); 1238 kmem_free(cpp, ccio->ccio_ndisks * sizeof(*cpp)); 1239 goto out; 1240 } 1241 1242 #ifdef DEBUG 1243 if (ccddebug & CCDB_INIT) 1244 for (i = 0; i < ccio->ccio_ndisks; ++i) 1245 printf("ccdioctl: component %d: %p\n", 1246 i, cpp[i]); 1247 #endif 1248 1249 for (i = 0; i < ccio->ccio_ndisks; ++i) { 1250 #ifdef DEBUG 1251 if (ccddebug & CCDB_INIT) 1252 printf("ccdioctl: lookedup = %d\n", lookedup); 1253 #endif 1254 error = pathbuf_copyin(cpp[i], &pb); 1255 if (error == 0) { 1256 error = dk_lookup(pb, l, &vpp[i]); 1257 } 1258 pathbuf_destroy(pb); 1259 if (error != 0) { 1260 for (j = 0; j < lookedup; ++j) 1261 (void)vn_close(vpp[j], FREAD|FWRITE, 1262 uc); 1263 kmem_free(vpp, ccio->ccio_ndisks * 1264 sizeof(*vpp)); 1265 kmem_free(cpp, ccio->ccio_ndisks * 1266 sizeof(*cpp)); 1267 goto out; 1268 } 1269 ++lookedup; 1270 } 1271 1272 /* Attach the disk. */ 1273 disk_attach(&cs->sc_dkdev); 1274 bufq_alloc(&cs->sc_bufq, "fcfs", 0); 1275 1276 /* 1277 * Initialize the ccd. Fills in the softc for us. 1278 */ 1279 if ((error = ccdinit(cs, cpp, vpp, l)) != 0) { 1280 for (j = 0; j < lookedup; ++j) 1281 (void)vn_close(vpp[j], FREAD|FWRITE, 1282 uc); 1283 kmem_free(vpp, ccio->ccio_ndisks * sizeof(*vpp)); 1284 kmem_free(cpp, ccio->ccio_ndisks * sizeof(*cpp)); 1285 disk_detach(&cs->sc_dkdev); 1286 bufq_free(cs->sc_bufq); 1287 goto out; 1288 } 1289 1290 /* We can free the temporary variables now. */ 1291 kmem_free(vpp, ccio->ccio_ndisks * sizeof(*vpp)); 1292 kmem_free(cpp, ccio->ccio_ndisks * sizeof(*cpp)); 1293 1294 /* 1295 * The ccd has been successfully initialized, so 1296 * we can place it into the array. Don't try to 1297 * read the disklabel until the disk has been attached, 1298 * because space for the disklabel is allocated 1299 * in disk_attach(); 1300 */ 1301 ccio->ccio_unit = unit; 1302 ccio->ccio_size = cs->sc_size; 1303 1304 /* Try and read the disklabel. */ 1305 ccdgetdisklabel(dev); 1306 disk_set_info(NULL, &cs->sc_dkdev, NULL); 1307 1308 /* discover wedges */ 1309 mutex_exit(&cs->sc_dvlock); 1310 dkwedge_discover(&cs->sc_dkdev); 1311 return 0; 1312 1313 case CCDIOCCLR: 1314 /* 1315 * Don't unconfigure if any other partitions are open 1316 * or if both the character and block flavors of this 1317 * partition are open. 1318 */ 1319 part = DISKPART(dev); 1320 pmask = (1 << part); 1321 if ((cs->sc_dkdev.dk_openmask & ~pmask) || 1322 ((cs->sc_dkdev.dk_bopenmask & pmask) && 1323 (cs->sc_dkdev.dk_copenmask & pmask))) { 1324 error = EBUSY; 1325 goto out; 1326 } 1327 1328 /* Delete all of our wedges. */ 1329 dkwedge_delall(&cs->sc_dkdev); 1330 1331 /* Stop new I/O, wait for in-flight I/O to complete. */ 1332 mutex_enter(cs->sc_iolock); 1333 cs->sc_flags &= ~(CCDF_INITED|CCDF_VLABEL); 1334 cs->sc_zap = true; 1335 while (disk_isbusy(&cs->sc_dkdev) || 1336 bufq_peek(cs->sc_bufq) != NULL || 1337 cs->sc_thread != NULL) { 1338 cv_broadcast(&cs->sc_push); 1339 (void)cv_timedwait(&cs->sc_stop, cs->sc_iolock, hz); 1340 } 1341 mutex_exit(cs->sc_iolock); 1342 1343 /* 1344 * Free ccd_softc information and clear entry. 1345 */ 1346 1347 /* Close the components and free their pathnames. */ 1348 for (i = 0; i < cs->sc_nccdisks; ++i) { 1349 /* 1350 * XXX: this close could potentially fail and 1351 * cause Bad Things. Maybe we need to force 1352 * the close to happen? 1353 */ 1354 #ifdef DEBUG 1355 if (ccddebug & CCDB_VNODE) 1356 vprint("CCDIOCCLR: vnode info", 1357 cs->sc_cinfo[i].ci_vp); 1358 #endif 1359 (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE, 1360 uc); 1361 kmem_free(cs->sc_cinfo[i].ci_path, 1362 cs->sc_cinfo[i].ci_pathlen); 1363 } 1364 1365 /* Free interleave index. */ 1366 for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) { 1367 kmem_free(cs->sc_itable[i].ii_index, 1368 cs->sc_itable[i].ii_indexsz); 1369 } 1370 1371 /* Free component info and interleave table. */ 1372 kmem_free(cs->sc_cinfo, cs->sc_nccdisks * 1373 sizeof(struct ccdcinfo)); 1374 kmem_free(cs->sc_itable, (cs->sc_nccdisks + 1) * 1375 sizeof(struct ccdiinfo)); 1376 1377 aprint_normal("%s: detached\n", cs->sc_xname); 1378 1379 /* Detach the disk. */ 1380 disk_detach(&cs->sc_dkdev); 1381 bufq_free(cs->sc_bufq); 1382 ccdput(cs); 1383 /* Don't break, otherwise cs is read again. */ 1384 return 0; 1385 1386 case DIOCCACHESYNC: 1387 /* 1388 * We pass this call down to all components and report 1389 * the first error we encounter. 1390 */ 1391 for (error = 0, i = 0; i < cs->sc_nccdisks; i++) { 1392 j = VOP_IOCTL(cs->sc_cinfo[i].ci_vp, cmd, data, 1393 flag, uc); 1394 if (j != 0 && error == 0) 1395 error = j; 1396 } 1397 break; 1398 1399 case DIOCWDINFO: 1400 case DIOCSDINFO: 1401 #ifdef __HAVE_OLD_DISKLABEL 1402 case ODIOCWDINFO: 1403 case ODIOCSDINFO: 1404 #endif 1405 { 1406 struct disklabel *lp; 1407 #ifdef __HAVE_OLD_DISKLABEL 1408 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { 1409 memset(&newlabel, 0, sizeof newlabel); 1410 memcpy(&newlabel, data, sizeof (struct olddisklabel)); 1411 lp = &newlabel; 1412 } else 1413 #endif 1414 lp = (struct disklabel *)data; 1415 1416 cs->sc_flags |= CCDF_LABELLING; 1417 1418 error = setdisklabel(cs->sc_dkdev.dk_label, 1419 lp, 0, cs->sc_dkdev.dk_cpulabel); 1420 if (error == 0) { 1421 if (cmd == DIOCWDINFO 1422 #ifdef __HAVE_OLD_DISKLABEL 1423 || cmd == ODIOCWDINFO 1424 #endif 1425 ) 1426 error = writedisklabel(CCDLABELDEV(dev), 1427 ccdstrategy, cs->sc_dkdev.dk_label, 1428 cs->sc_dkdev.dk_cpulabel); 1429 } 1430 1431 cs->sc_flags &= ~CCDF_LABELLING; 1432 break; 1433 } 1434 1435 case DIOCKLABEL: 1436 if (*(int *)data != 0) 1437 cs->sc_flags |= CCDF_KLABEL; 1438 else 1439 cs->sc_flags &= ~CCDF_KLABEL; 1440 break; 1441 1442 case DIOCWLABEL: 1443 if (*(int *)data != 0) 1444 cs->sc_flags |= CCDF_WLABEL; 1445 else 1446 cs->sc_flags &= ~CCDF_WLABEL; 1447 break; 1448 1449 case DIOCGDEFLABEL: 1450 ccdgetdefaultlabel(cs, (struct disklabel *)data); 1451 break; 1452 1453 #ifdef __HAVE_OLD_DISKLABEL 1454 case ODIOCGDEFLABEL: 1455 ccdgetdefaultlabel(cs, &newlabel); 1456 if (newlabel.d_npartitions > OLDMAXPARTITIONS) 1457 return ENOTTY; 1458 memcpy(data, &newlabel, sizeof (struct olddisklabel)); 1459 break; 1460 #endif 1461 1462 default: 1463 error = ENOTTY; 1464 } 1465 1466 out: 1467 mutex_exit(&cs->sc_dvlock); 1468 return (error); 1469 } 1470 1471 static int 1472 ccdsize(dev_t dev) 1473 { 1474 struct ccd_softc *cs; 1475 struct disklabel *lp; 1476 int part, unit, omask, size; 1477 1478 unit = ccdunit(dev); 1479 if ((cs = ccdget(unit, 0)) == NULL) 1480 return -1; 1481 1482 if ((cs->sc_flags & CCDF_INITED) == 0) 1483 return (-1); 1484 1485 part = DISKPART(dev); 1486 omask = cs->sc_dkdev.dk_openmask & (1 << part); 1487 lp = cs->sc_dkdev.dk_label; 1488 1489 if (omask == 0 && ccdopen(dev, 0, S_IFBLK, curlwp)) 1490 return (-1); 1491 1492 if (lp->d_partitions[part].p_fstype != FS_SWAP) 1493 size = -1; 1494 else 1495 size = lp->d_partitions[part].p_size * 1496 (lp->d_secsize / DEV_BSIZE); 1497 1498 if (omask == 0 && ccdclose(dev, 0, S_IFBLK, curlwp)) 1499 return (-1); 1500 1501 return (size); 1502 } 1503 1504 static void 1505 ccdgetdefaultlabel(struct ccd_softc *cs, struct disklabel *lp) 1506 { 1507 struct ccdgeom *ccg = &cs->sc_geom; 1508 1509 memset(lp, 0, sizeof(*lp)); 1510 1511 if (cs->sc_size > UINT32_MAX) 1512 lp->d_secperunit = UINT32_MAX; 1513 else 1514 lp->d_secperunit = cs->sc_size; 1515 lp->d_secsize = ccg->ccg_secsize; 1516 lp->d_nsectors = ccg->ccg_nsectors; 1517 lp->d_ntracks = ccg->ccg_ntracks; 1518 lp->d_ncylinders = ccg->ccg_ncylinders; 1519 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1520 1521 strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename)); 1522 lp->d_type = DKTYPE_CCD; 1523 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 1524 lp->d_rpm = 3600; 1525 lp->d_interleave = 1; 1526 lp->d_flags = 0; 1527 1528 lp->d_partitions[RAW_PART].p_offset = 0; 1529 lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; 1530 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 1531 lp->d_npartitions = RAW_PART + 1; 1532 1533 lp->d_magic = DISKMAGIC; 1534 lp->d_magic2 = DISKMAGIC; 1535 lp->d_checksum = dkcksum(cs->sc_dkdev.dk_label); 1536 } 1537 1538 /* 1539 * Read the disklabel from the ccd. If one is not present, fake one 1540 * up. 1541 */ 1542 static void 1543 ccdgetdisklabel(dev_t dev) 1544 { 1545 int unit = ccdunit(dev); 1546 struct ccd_softc *cs; 1547 const char *errstring; 1548 struct disklabel *lp; 1549 struct cpu_disklabel *clp; 1550 1551 if ((cs = ccdget(unit, 0)) == NULL) 1552 return; 1553 lp = cs->sc_dkdev.dk_label; 1554 clp = cs->sc_dkdev.dk_cpulabel; 1555 KASSERT(mutex_owned(&cs->sc_dvlock)); 1556 1557 memset(clp, 0, sizeof(*clp)); 1558 1559 ccdgetdefaultlabel(cs, lp); 1560 1561 /* 1562 * Call the generic disklabel extraction routine. 1563 */ 1564 cs->sc_flags |= CCDF_RLABEL; 1565 if ((cs->sc_flags & CCDF_NOLABEL) != 0) 1566 errstring = "CCDF_NOLABEL set; ignoring on-disk label"; 1567 else 1568 errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy, 1569 cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel); 1570 if (errstring) 1571 ccdmakedisklabel(cs); 1572 else { 1573 int i; 1574 struct partition *pp; 1575 1576 /* 1577 * Sanity check whether the found disklabel is valid. 1578 * 1579 * This is necessary since total size of ccd may vary 1580 * when an interleave is changed even though exactly 1581 * same componets are used, and old disklabel may used 1582 * if that is found. 1583 */ 1584 if (lp->d_secperunit < UINT32_MAX ? 1585 lp->d_secperunit != cs->sc_size : 1586 lp->d_secperunit > cs->sc_size) 1587 printf("WARNING: %s: " 1588 "total sector size in disklabel (%ju) != " 1589 "the size of ccd (%ju)\n", cs->sc_xname, 1590 (uintmax_t)lp->d_secperunit, 1591 (uintmax_t)cs->sc_size); 1592 for (i = 0; i < lp->d_npartitions; i++) { 1593 pp = &lp->d_partitions[i]; 1594 if (pp->p_offset + pp->p_size > cs->sc_size) 1595 printf("WARNING: %s: end of partition `%c' " 1596 "exceeds the size of ccd (%ju)\n", 1597 cs->sc_xname, 'a' + i, (uintmax_t)cs->sc_size); 1598 } 1599 } 1600 1601 #ifdef DEBUG 1602 /* It's actually extremely common to have unlabeled ccds. */ 1603 if (ccddebug & CCDB_LABEL) 1604 if (errstring != NULL) 1605 printf("%s: %s\n", cs->sc_xname, errstring); 1606 #endif 1607 1608 /* In-core label now valid. */ 1609 cs->sc_flags = (cs->sc_flags | CCDF_VLABEL) & ~CCDF_RLABEL; 1610 } 1611 1612 /* 1613 * Take care of things one might want to take care of in the event 1614 * that a disklabel isn't present. 1615 */ 1616 static void 1617 ccdmakedisklabel(struct ccd_softc *cs) 1618 { 1619 struct disklabel *lp = cs->sc_dkdev.dk_label; 1620 1621 /* 1622 * For historical reasons, if there's no disklabel present 1623 * the raw partition must be marked FS_BSDFFS. 1624 */ 1625 lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS; 1626 1627 strncpy(lp->d_packname, "default label", sizeof(lp->d_packname)); 1628 1629 lp->d_checksum = dkcksum(lp); 1630 } 1631 1632 #ifdef DEBUG 1633 static void 1634 printiinfo(struct ccdiinfo *ii) 1635 { 1636 int ix, i; 1637 1638 for (ix = 0; ii->ii_ndisk; ix++, ii++) { 1639 printf(" itab[%d]: #dk %d sblk %" PRId64 " soff %" PRId64, 1640 ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff); 1641 for (i = 0; i < ii->ii_ndisk; i++) 1642 printf(" %d", ii->ii_index[i]); 1643 printf("\n"); 1644 } 1645 } 1646 #endif 1647 1648 MODULE(MODULE_CLASS_DRIVER, ccd, "dk_subr"); 1649 1650 static int 1651 ccd_modcmd(modcmd_t cmd, void *arg) 1652 { 1653 int error = 0; 1654 #ifdef _MODULE 1655 int bmajor = -1, cmajor = -1; 1656 #endif 1657 1658 1659 switch (cmd) { 1660 case MODULE_CMD_INIT: 1661 #ifdef _MODULE 1662 ccdattach(0); 1663 1664 error = devsw_attach("ccd", &ccd_bdevsw, &bmajor, 1665 &ccd_cdevsw, &cmajor); 1666 #endif 1667 break; 1668 1669 case MODULE_CMD_FINI: 1670 #ifdef _MODULE 1671 mutex_enter(&ccd_lock); 1672 if (ccd_nactive) { 1673 mutex_exit(&ccd_lock); 1674 error = EBUSY; 1675 } else { 1676 mutex_exit(&ccd_lock); 1677 error = devsw_detach(&ccd_bdevsw, &ccd_cdevsw); 1678 ccddetach(); 1679 } 1680 #endif 1681 break; 1682 1683 case MODULE_CMD_STAT: 1684 return ENOTTY; 1685 1686 default: 1687 return ENOTTY; 1688 } 1689 1690 return error; 1691 } 1692 1693 static int 1694 ccd_units_sysctl(SYSCTLFN_ARGS) 1695 { 1696 struct sysctlnode node; 1697 struct ccd_softc *sc; 1698 int error, i, nccd, *units; 1699 size_t size; 1700 1701 nccd = 0; 1702 mutex_enter(&ccd_lock); 1703 LIST_FOREACH(sc, &ccds, sc_link) 1704 nccd++; 1705 mutex_exit(&ccd_lock); 1706 1707 if (nccd != 0) { 1708 size = nccd * sizeof(*units); 1709 units = kmem_zalloc(size, KM_SLEEP); 1710 if (units == NULL) 1711 return ENOMEM; 1712 1713 i = 0; 1714 mutex_enter(&ccd_lock); 1715 LIST_FOREACH(sc, &ccds, sc_link) { 1716 if (i >= nccd) 1717 break; 1718 units[i] = sc->sc_unit; 1719 } 1720 mutex_exit(&ccd_lock); 1721 } else { 1722 units = NULL; 1723 size = 0; 1724 } 1725 1726 node = *rnode; 1727 node.sysctl_data = units; 1728 node.sysctl_size = size; 1729 1730 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1731 if (units) 1732 kmem_free(units, size); 1733 return error; 1734 } 1735 1736 static int 1737 ccd_info_sysctl(SYSCTLFN_ARGS) 1738 { 1739 struct sysctlnode node; 1740 struct ccddiskinfo ccd; 1741 struct ccd_softc *sc; 1742 int unit; 1743 1744 if (newp == NULL || newlen != sizeof(int)) 1745 return EINVAL; 1746 1747 unit = *(const int *)newp; 1748 newp = NULL; 1749 newlen = 0; 1750 ccd.ccd_ndisks = ~0; 1751 mutex_enter(&ccd_lock); 1752 LIST_FOREACH(sc, &ccds, sc_link) { 1753 if (sc->sc_unit == unit) { 1754 ccd.ccd_ileave = sc->sc_ileave; 1755 ccd.ccd_size = sc->sc_size; 1756 ccd.ccd_ndisks = sc->sc_nccdisks; 1757 ccd.ccd_flags = sc->sc_flags; 1758 break; 1759 } 1760 } 1761 mutex_exit(&ccd_lock); 1762 1763 if (ccd.ccd_ndisks == ~0) 1764 return ENOENT; 1765 1766 node = *rnode; 1767 node.sysctl_data = &ccd; 1768 node.sysctl_size = sizeof(ccd); 1769 1770 return sysctl_lookup(SYSCTLFN_CALL(&node)); 1771 } 1772 1773 static int 1774 ccd_components_sysctl(SYSCTLFN_ARGS) 1775 { 1776 struct sysctlnode node; 1777 int error, unit; 1778 size_t size; 1779 char *names, *p, *ep; 1780 struct ccd_softc *sc; 1781 1782 if (newp == NULL || newlen != sizeof(int)) 1783 return EINVAL; 1784 1785 size = 0; 1786 unit = *(const int *)newp; 1787 newp = NULL; 1788 newlen = 0; 1789 mutex_enter(&ccd_lock); 1790 LIST_FOREACH(sc, &ccds, sc_link) 1791 if (sc->sc_unit == unit) { 1792 for (size_t i = 0; i < sc->sc_nccdisks; i++) 1793 size += strlen(sc->sc_cinfo[i].ci_path) + 1; 1794 break; 1795 } 1796 mutex_exit(&ccd_lock); 1797 1798 if (size == 0) 1799 return ENOENT; 1800 names = kmem_zalloc(size, KM_SLEEP); 1801 if (names == NULL) 1802 return ENOMEM; 1803 1804 p = names; 1805 ep = names + size; 1806 mutex_enter(&ccd_lock); 1807 LIST_FOREACH(sc, &ccds, sc_link) 1808 if (sc->sc_unit == unit) { 1809 for (size_t i = 0; i < sc->sc_nccdisks; i++) { 1810 char *d = sc->sc_cinfo[i].ci_path; 1811 while (p < ep && (*p++ = *d++) != '\0') 1812 continue; 1813 } 1814 break; 1815 } 1816 mutex_exit(&ccd_lock); 1817 1818 node = *rnode; 1819 node.sysctl_data = names; 1820 node.sysctl_size = ep - names; 1821 1822 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1823 kmem_free(names, size); 1824 return error; 1825 } 1826 1827 SYSCTL_SETUP(sysctl_kern_ccd_setup, "sysctl kern.ccd subtree setup") 1828 { 1829 const struct sysctlnode *node = NULL; 1830 1831 sysctl_createv(clog, 0, NULL, &node, 1832 CTLFLAG_PERMANENT, 1833 CTLTYPE_NODE, "ccd", 1834 SYSCTL_DESCR("ConCatenated Disk state"), 1835 NULL, 0, NULL, 0, 1836 CTL_KERN, CTL_CREATE, CTL_EOL); 1837 1838 if (node == NULL) 1839 return; 1840 1841 sysctl_createv(clog, 0, &node, NULL, 1842 CTLFLAG_PERMANENT | CTLFLAG_READONLY, 1843 CTLTYPE_STRUCT, "units", 1844 SYSCTL_DESCR("List of ccd unit numbers"), 1845 ccd_units_sysctl, 0, NULL, 0, 1846 CTL_CREATE, CTL_EOL); 1847 sysctl_createv(clog, 0, &node, NULL, 1848 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 1849 CTLTYPE_STRUCT, "info", 1850 SYSCTL_DESCR("Information about a CCD unit"), 1851 ccd_info_sysctl, 0, NULL, 0, 1852 CTL_CREATE, CTL_EOL); 1853 sysctl_createv(clog, 0, &node, NULL, 1854 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 1855 CTLTYPE_STRUCT, "components", 1856 SYSCTL_DESCR("Information about CCD components"), 1857 ccd_components_sysctl, 0, NULL, 0, 1858 CTL_CREATE, CTL_EOL); 1859 } 1860