1 /*- 2 * SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) 3 * 4 * Copyright (c) 2003 Poul-Henning Kamp. 5 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 * 32 * $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ 33 */ 34 35 /*- 36 * Copyright (c) 1988 University of Utah. 37 * Copyright (c) 1990, 1993 38 * The Regents of the University of California. All rights reserved. 39 * 40 * This code is derived from software contributed to Berkeley by 41 * the Systems Programming Group of the University of Utah Computer 42 * Science Department. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. Neither the name of the University nor the names of its contributors 53 * may be used to endorse or promote products derived from this software 54 * without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 * 68 * from: Utah $Hdr: cd.c 1.6 90/11/28$ 69 */ 70 71 /* 72 * Dynamic configuration and disklabel support by: 73 * Jason R. Thorpe <thorpej@nas.nasa.gov> 74 * Numerical Aerodynamic Simulation Facility 75 * Mail Stop 258-6 76 * NASA Ames Research Center 77 * Moffett Field, CA 94035 78 */ 79 80 #include <sys/cdefs.h> 81 #include <sys/param.h> 82 #include <sys/systm.h> 83 #include <sys/kernel.h> 84 #include <sys/module.h> 85 #include <sys/bio.h> 86 #include <sys/malloc.h> 87 #include <sys/sbuf.h> 88 #include <geom/geom.h> 89 90 /* 91 * Number of blocks to untouched in front of a component partition. 92 * This is to avoid violating its disklabel area when it starts at the 93 * beginning of the slice. 94 */ 95 #if !defined(CCD_OFFSET) 96 #define CCD_OFFSET 16 97 #endif 98 99 /* sc_flags */ 100 #define CCDF_UNIFORM 0x02 /* use LCCD of sizes for uniform interleave */ 101 #define CCDF_MIRROR 0x04 /* use mirroring */ 102 #define CCDF_NO_OFFSET 0x08 /* do not leave space in front */ 103 #define CCDF_LINUX 0x10 /* use Linux compatibility mode */ 104 105 /* Mask of user-settable ccd flags. */ 106 #define CCDF_USERMASK (CCDF_UNIFORM|CCDF_MIRROR) 107 108 /* 109 * Interleave description table. 110 * Computed at boot time to speed irregular-interleave lookups. 111 * The idea is that we interleave in "groups". First we interleave 112 * evenly over all component disks up to the size of the smallest 113 * component (the first group), then we interleave evenly over all 114 * remaining disks up to the size of the next-smallest (second group), 115 * and so on. 116 * 117 * Each table entry describes the interleave characteristics of one 118 * of these groups. For example if a concatenated disk consisted of 119 * three components of 5, 3, and 7 DEV_BSIZE blocks interleaved at 120 * DEV_BSIZE (1), the table would have three entries: 121 * 122 * ndisk startblk startoff dev 123 * 3 0 0 0, 1, 2 124 * 2 9 3 0, 2 125 * 1 13 5 2 126 * 0 - - - 127 * 128 * which says that the first nine blocks (0-8) are interleaved over 129 * 3 disks (0, 1, 2) starting at block offset 0 on any component disk, 130 * the next 4 blocks (9-12) are interleaved over 2 disks (0, 2) starting 131 * at component block 3, and the remaining blocks (13-14) are on disk 132 * 2 starting at offset 5. 133 */ 134 struct ccdiinfo { 135 int ii_ndisk; /* # of disks range is interleaved over */ 136 daddr_t ii_startblk; /* starting scaled block # for range */ 137 daddr_t ii_startoff; /* starting component offset (block #) */ 138 int *ii_index; /* ordered list of components in range */ 139 }; 140 141 /* 142 * Component info table. 143 * Describes a single component of a concatenated disk. 144 */ 145 struct ccdcinfo { 146 daddr_t ci_size; /* size */ 147 struct g_provider *ci_provider; /* provider */ 148 struct g_consumer *ci_consumer; /* consumer */ 149 }; 150 151 /* 152 * A concatenated disk is described by this structure. 153 */ 154 155 struct ccd_s { 156 LIST_ENTRY(ccd_s) list; 157 158 int sc_unit; /* logical unit number */ 159 int sc_flags; /* flags */ 160 daddr_t sc_size; /* size of ccd */ 161 int sc_ileave; /* interleave */ 162 u_int sc_ndisks; /* number of components */ 163 struct ccdcinfo *sc_cinfo; /* component info */ 164 struct ccdiinfo *sc_itable; /* interleave table */ 165 uint32_t sc_secsize; /* # bytes per sector */ 166 int sc_pick; /* side of mirror picked */ 167 daddr_t sc_blk[2]; /* mirror localization */ 168 uint32_t sc_offset; /* actual offset used */ 169 }; 170 171 static g_start_t g_ccd_start; 172 static void ccdiodone(struct bio *bp); 173 static void ccdinterleave(struct ccd_s *); 174 static int ccdinit(struct gctl_req *req, struct ccd_s *); 175 static int ccdbuffer(struct bio **ret, struct ccd_s *, 176 struct bio *, daddr_t, caddr_t, long); 177 178 static void 179 g_ccd_orphan(struct g_consumer *cp) 180 { 181 /* 182 * XXX: We don't do anything here. It is not obvious 183 * XXX: what DTRT would be, so we do what the previous 184 * XXX: code did: ignore it and let the user cope. 185 */ 186 } 187 188 static int 189 g_ccd_access(struct g_provider *pp, int dr, int dw, int de) 190 { 191 struct g_geom *gp; 192 struct g_consumer *cp1, *cp2; 193 int error; 194 195 de += dr; 196 de += dw; 197 198 gp = pp->geom; 199 error = ENXIO; 200 LIST_FOREACH(cp1, &gp->consumer, consumer) { 201 error = g_access(cp1, dr, dw, de); 202 if (error) { 203 LIST_FOREACH(cp2, &gp->consumer, consumer) { 204 if (cp1 == cp2) 205 break; 206 g_access(cp2, -dr, -dw, -de); 207 } 208 break; 209 } 210 } 211 return (error); 212 } 213 214 /* 215 * Free the softc and its substructures. 216 */ 217 static void 218 g_ccd_freesc(struct ccd_s *sc) 219 { 220 struct ccdiinfo *ii; 221 222 g_free(sc->sc_cinfo); 223 if (sc->sc_itable != NULL) { 224 for (ii = sc->sc_itable; ii->ii_ndisk > 0; ii++) 225 g_free(ii->ii_index); 226 g_free(sc->sc_itable); 227 } 228 g_free(sc); 229 } 230 231 static int 232 ccdinit(struct gctl_req *req, struct ccd_s *cs) 233 { 234 struct ccdcinfo *ci; 235 daddr_t size; 236 int ix; 237 daddr_t minsize; 238 int maxsecsize; 239 off_t mediasize; 240 u_int sectorsize; 241 242 cs->sc_size = 0; 243 244 maxsecsize = 0; 245 minsize = 0; 246 247 if (cs->sc_flags & CCDF_LINUX) { 248 cs->sc_offset = 0; 249 cs->sc_ileave *= 2; 250 if (cs->sc_flags & CCDF_MIRROR && cs->sc_ndisks != 2) 251 gctl_error(req, "Mirror mode for Linux raids is " 252 "only supported with 2 devices"); 253 } else { 254 if (cs->sc_flags & CCDF_NO_OFFSET) 255 cs->sc_offset = 0; 256 else 257 cs->sc_offset = CCD_OFFSET; 258 } 259 for (ix = 0; ix < cs->sc_ndisks; ix++) { 260 ci = &cs->sc_cinfo[ix]; 261 262 mediasize = ci->ci_provider->mediasize; 263 sectorsize = ci->ci_provider->sectorsize; 264 if (sectorsize > maxsecsize) 265 maxsecsize = sectorsize; 266 size = mediasize / DEV_BSIZE - cs->sc_offset; 267 268 /* Truncate to interleave boundary */ 269 270 if (cs->sc_ileave > 1) 271 size -= size % cs->sc_ileave; 272 273 if (size == 0) { 274 gctl_error(req, "Component %s has effective size zero", 275 ci->ci_provider->name); 276 return(ENODEV); 277 } 278 279 if (minsize == 0 || size < minsize) 280 minsize = size; 281 ci->ci_size = size; 282 cs->sc_size += size; 283 } 284 285 /* 286 * Don't allow the interleave to be smaller than 287 * the biggest component sector. 288 */ 289 if ((cs->sc_ileave > 0) && 290 (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { 291 gctl_error(req, "Interleave to small for sector size"); 292 return(EINVAL); 293 } 294 295 /* 296 * If uniform interleave is desired set all sizes to that of 297 * the smallest component. This will guarantee that a single 298 * interleave table is generated. 299 * 300 * Lost space must be taken into account when calculating the 301 * overall size. Half the space is lost when CCDF_MIRROR is 302 * specified. 303 */ 304 if (cs->sc_flags & CCDF_UNIFORM) { 305 for (ix = 0; ix < cs->sc_ndisks; ix++) { 306 ci = &cs->sc_cinfo[ix]; 307 ci->ci_size = minsize; 308 } 309 cs->sc_size = cs->sc_ndisks * minsize; 310 } 311 312 if (cs->sc_flags & CCDF_MIRROR) { 313 /* 314 * Check to see if an even number of components 315 * have been specified. The interleave must also 316 * be non-zero in order for us to be able to 317 * guarantee the topology. 318 */ 319 if (cs->sc_ndisks % 2) { 320 gctl_error(req, 321 "Mirroring requires an even number of disks"); 322 return(EINVAL); 323 } 324 if (cs->sc_ileave == 0) { 325 gctl_error(req, 326 "An interleave must be specified when mirroring"); 327 return(EINVAL); 328 } 329 cs->sc_size = (cs->sc_ndisks/2) * minsize; 330 } 331 332 /* 333 * Construct the interleave table. 334 */ 335 ccdinterleave(cs); 336 337 /* 338 * Create pseudo-geometry based on 1MB cylinders. It's 339 * pretty close. 340 */ 341 cs->sc_secsize = maxsecsize; 342 343 return (0); 344 } 345 346 static void 347 ccdinterleave(struct ccd_s *cs) 348 { 349 struct ccdcinfo *ci, *smallci; 350 struct ccdiinfo *ii; 351 daddr_t bn, lbn; 352 int ix; 353 daddr_t size; 354 355 /* 356 * Allocate an interleave table. The worst case occurs when each 357 * of N disks is of a different size, resulting in N interleave 358 * tables. 359 * 360 * Chances are this is too big, but we don't care. 361 */ 362 size = (cs->sc_ndisks + 1) * sizeof(struct ccdiinfo); 363 cs->sc_itable = g_malloc(size, M_WAITOK | M_ZERO); 364 365 /* 366 * Trivial case: no interleave (actually interleave of disk size). 367 * Each table entry represents a single component in its entirety. 368 * 369 * An interleave of 0 may not be used with a mirror setup. 370 */ 371 if (cs->sc_ileave == 0) { 372 bn = 0; 373 ii = cs->sc_itable; 374 375 for (ix = 0; ix < cs->sc_ndisks; ix++) { 376 /* Allocate space for ii_index. */ 377 ii->ii_index = g_malloc(sizeof(int), M_WAITOK); 378 ii->ii_ndisk = 1; 379 ii->ii_startblk = bn; 380 ii->ii_startoff = 0; 381 ii->ii_index[0] = ix; 382 bn += cs->sc_cinfo[ix].ci_size; 383 ii++; 384 } 385 ii->ii_ndisk = 0; 386 return; 387 } 388 389 /* 390 * The following isn't fast or pretty; it doesn't have to be. 391 */ 392 size = 0; 393 bn = lbn = 0; 394 for (ii = cs->sc_itable; ; ii++) { 395 /* 396 * Allocate space for ii_index. We might allocate more then 397 * we use. 398 */ 399 ii->ii_index = g_malloc((sizeof(int) * cs->sc_ndisks), 400 M_WAITOK); 401 402 /* 403 * Locate the smallest of the remaining components 404 */ 405 smallci = NULL; 406 for (ci = cs->sc_cinfo; ci < &cs->sc_cinfo[cs->sc_ndisks]; 407 ci++) { 408 if (ci->ci_size > size && 409 (smallci == NULL || 410 ci->ci_size < smallci->ci_size)) { 411 smallci = ci; 412 } 413 } 414 415 /* 416 * Nobody left, all done 417 */ 418 if (smallci == NULL) { 419 ii->ii_ndisk = 0; 420 g_free(ii->ii_index); 421 ii->ii_index = NULL; 422 break; 423 } 424 425 /* 426 * Record starting logical block using an sc_ileave blocksize. 427 */ 428 ii->ii_startblk = bn / cs->sc_ileave; 429 430 /* 431 * Record starting component block using an sc_ileave 432 * blocksize. This value is relative to the beginning of 433 * a component disk. 434 */ 435 ii->ii_startoff = lbn; 436 437 /* 438 * Determine how many disks take part in this interleave 439 * and record their indices. 440 */ 441 ix = 0; 442 for (ci = cs->sc_cinfo; 443 ci < &cs->sc_cinfo[cs->sc_ndisks]; ci++) { 444 if (ci->ci_size >= smallci->ci_size) { 445 ii->ii_index[ix++] = ci - cs->sc_cinfo; 446 } 447 } 448 ii->ii_ndisk = ix; 449 bn += ix * (smallci->ci_size - size); 450 lbn = smallci->ci_size / cs->sc_ileave; 451 size = smallci->ci_size; 452 } 453 } 454 455 static void 456 g_ccd_start(struct bio *bp) 457 { 458 long bcount, rcount; 459 struct bio *cbp[2]; 460 caddr_t addr; 461 daddr_t bn; 462 int err; 463 struct ccd_s *cs; 464 465 cs = bp->bio_to->geom->softc; 466 467 /* 468 * Block all GETATTR requests, we wouldn't know which of our 469 * subdevices we should ship it off to. 470 * XXX: this may not be the right policy. 471 */ 472 if(bp->bio_cmd == BIO_GETATTR) { 473 g_io_deliver(bp, EINVAL); 474 return; 475 } 476 477 /* 478 * Translate the partition-relative block number to an absolute. 479 */ 480 bn = bp->bio_offset / cs->sc_secsize; 481 482 /* 483 * Allocate component buffers and fire off the requests 484 */ 485 addr = bp->bio_data; 486 for (bcount = bp->bio_length; bcount > 0; bcount -= rcount) { 487 err = ccdbuffer(cbp, cs, bp, bn, addr, bcount); 488 if (err) { 489 bp->bio_completed += bcount; 490 if (bp->bio_error == 0) 491 bp->bio_error = err; 492 if (bp->bio_completed == bp->bio_length) 493 g_io_deliver(bp, bp->bio_error); 494 return; 495 } 496 rcount = cbp[0]->bio_length; 497 498 if (cs->sc_flags & CCDF_MIRROR) { 499 /* 500 * Mirroring. Writes go to both disks, reads are 501 * taken from whichever disk seems most appropriate. 502 * 503 * We attempt to localize reads to the disk whos arm 504 * is nearest the read request. We ignore seeks due 505 * to writes when making this determination and we 506 * also try to avoid hogging. 507 */ 508 if (cbp[0]->bio_cmd != BIO_READ) { 509 g_io_request(cbp[0], cbp[0]->bio_from); 510 g_io_request(cbp[1], cbp[1]->bio_from); 511 } else { 512 int pick = cs->sc_pick; 513 daddr_t range = cs->sc_size / 16; 514 515 if (bn < cs->sc_blk[pick] - range || 516 bn > cs->sc_blk[pick] + range 517 ) { 518 cs->sc_pick = pick = 1 - pick; 519 } 520 cs->sc_blk[pick] = bn + btodb(rcount); 521 g_io_request(cbp[pick], cbp[pick]->bio_from); 522 } 523 } else { 524 /* 525 * Not mirroring 526 */ 527 g_io_request(cbp[0], cbp[0]->bio_from); 528 } 529 bn += btodb(rcount); 530 addr += rcount; 531 } 532 } 533 534 /* 535 * Build a component buffer header. 536 */ 537 static int 538 ccdbuffer(struct bio **cb, struct ccd_s *cs, struct bio *bp, daddr_t bn, caddr_t addr, long bcount) 539 { 540 struct ccdcinfo *ci, *ci2 = NULL; 541 struct bio *cbp; 542 daddr_t cbn, cboff; 543 off_t cbc; 544 545 /* 546 * Determine which component bn falls in. 547 */ 548 cbn = bn; 549 cboff = 0; 550 551 if (cs->sc_ileave == 0) { 552 /* 553 * Serially concatenated and neither a mirror nor a parity 554 * config. This is a special case. 555 */ 556 daddr_t sblk; 557 558 sblk = 0; 559 for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++) 560 sblk += ci->ci_size; 561 cbn -= sblk; 562 } else { 563 struct ccdiinfo *ii; 564 int ccdisk, off; 565 566 /* 567 * Calculate cbn, the logical superblock (sc_ileave chunks), 568 * and cboff, a normal block offset (DEV_BSIZE chunks) relative 569 * to cbn. 570 */ 571 cboff = cbn % cs->sc_ileave; /* DEV_BSIZE gran */ 572 cbn = cbn / cs->sc_ileave; /* DEV_BSIZE * ileave gran */ 573 574 /* 575 * Figure out which interleave table to use. 576 */ 577 for (ii = cs->sc_itable; ii->ii_ndisk; ii++) { 578 if (ii->ii_startblk > cbn) 579 break; 580 } 581 ii--; 582 583 /* 584 * off is the logical superblock relative to the beginning 585 * of this interleave block. 586 */ 587 off = cbn - ii->ii_startblk; 588 589 /* 590 * We must calculate which disk component to use (ccdisk), 591 * and recalculate cbn to be the superblock relative to 592 * the beginning of the component. This is typically done by 593 * adding 'off' and ii->ii_startoff together. However, 'off' 594 * must typically be divided by the number of components in 595 * this interleave array to be properly convert it from a 596 * CCD-relative logical superblock number to a 597 * component-relative superblock number. 598 */ 599 if (ii->ii_ndisk == 1) { 600 /* 601 * When we have just one disk, it can't be a mirror 602 * or a parity config. 603 */ 604 ccdisk = ii->ii_index[0]; 605 cbn = ii->ii_startoff + off; 606 } else { 607 if (cs->sc_flags & CCDF_MIRROR) { 608 /* 609 * We have forced a uniform mapping, resulting 610 * in a single interleave array. We double 611 * up on the first half of the available 612 * components and our mirror is in the second 613 * half. This only works with a single 614 * interleave array because doubling up 615 * doubles the number of sectors, so there 616 * cannot be another interleave array because 617 * the next interleave array's calculations 618 * would be off. 619 */ 620 int ndisk2 = ii->ii_ndisk / 2; 621 ccdisk = ii->ii_index[off % ndisk2]; 622 cbn = ii->ii_startoff + off / ndisk2; 623 ci2 = &cs->sc_cinfo[ccdisk + ndisk2]; 624 } else { 625 ccdisk = ii->ii_index[off % ii->ii_ndisk]; 626 cbn = ii->ii_startoff + off / ii->ii_ndisk; 627 } 628 } 629 630 ci = &cs->sc_cinfo[ccdisk]; 631 632 /* 633 * Convert cbn from a superblock to a normal block so it 634 * can be used to calculate (along with cboff) the normal 635 * block index into this particular disk. 636 */ 637 cbn *= cs->sc_ileave; 638 } 639 640 /* 641 * Fill in the component buf structure. 642 */ 643 cbp = g_clone_bio(bp); 644 if (cbp == NULL) 645 return (ENOMEM); 646 cbp->bio_done = g_std_done; 647 cbp->bio_offset = dbtob(cbn + cboff + cs->sc_offset); 648 cbp->bio_data = addr; 649 if (cs->sc_ileave == 0) 650 cbc = dbtob((off_t)(ci->ci_size - cbn)); 651 else 652 cbc = dbtob((off_t)(cs->sc_ileave - cboff)); 653 cbp->bio_length = (cbc < bcount) ? cbc : bcount; 654 655 cbp->bio_from = ci->ci_consumer; 656 cb[0] = cbp; 657 658 if (cs->sc_flags & CCDF_MIRROR) { 659 cbp = g_clone_bio(bp); 660 if (cbp == NULL) 661 return (ENOMEM); 662 cbp->bio_done = cb[0]->bio_done = ccdiodone; 663 cbp->bio_offset = cb[0]->bio_offset; 664 cbp->bio_data = cb[0]->bio_data; 665 cbp->bio_length = cb[0]->bio_length; 666 cbp->bio_from = ci2->ci_consumer; 667 cbp->bio_caller1 = cb[0]; 668 cb[0]->bio_caller1 = cbp; 669 cb[1] = cbp; 670 } 671 return (0); 672 } 673 674 /* 675 * Called only for mirrored operations. 676 */ 677 static void 678 ccdiodone(struct bio *cbp) 679 { 680 struct bio *mbp, *pbp; 681 682 mbp = cbp->bio_caller1; 683 pbp = cbp->bio_parent; 684 685 if (pbp->bio_cmd == BIO_READ) { 686 if (cbp->bio_error == 0) { 687 /* We will not be needing the partner bio */ 688 if (mbp != NULL) { 689 pbp->bio_inbed++; 690 g_destroy_bio(mbp); 691 } 692 g_std_done(cbp); 693 return; 694 } 695 if (mbp != NULL) { 696 /* Try partner the bio instead */ 697 mbp->bio_caller1 = NULL; 698 pbp->bio_inbed++; 699 g_destroy_bio(cbp); 700 g_io_request(mbp, mbp->bio_from); 701 /* 702 * XXX: If this comes back OK, we should actually 703 * try to write the good data on the failed mirror 704 */ 705 return; 706 } 707 g_std_done(cbp); 708 return; 709 } 710 if (mbp != NULL) { 711 mbp->bio_caller1 = NULL; 712 pbp->bio_inbed++; 713 if (cbp->bio_error != 0 && pbp->bio_error == 0) 714 pbp->bio_error = cbp->bio_error; 715 g_destroy_bio(cbp); 716 return; 717 } 718 g_std_done(cbp); 719 } 720 721 static void 722 g_ccd_create(struct gctl_req *req, struct g_class *mp) 723 { 724 int *unit, *ileave, *nprovider; 725 struct g_geom *gp; 726 struct g_consumer *cp; 727 struct g_provider *pp; 728 struct ccd_s *sc; 729 struct sbuf *sb; 730 char buf[20]; 731 int i, error; 732 733 g_topology_assert(); 734 unit = gctl_get_paraml(req, "unit", sizeof (*unit)); 735 if (unit == NULL) { 736 gctl_error(req, "unit parameter not given"); 737 return; 738 } 739 ileave = gctl_get_paraml(req, "ileave", sizeof (*ileave)); 740 if (ileave == NULL) { 741 gctl_error(req, "ileave parameter not given"); 742 return; 743 } 744 nprovider = gctl_get_paraml(req, "nprovider", sizeof (*nprovider)); 745 if (nprovider == NULL) { 746 gctl_error(req, "nprovider parameter not given"); 747 return; 748 } 749 750 /* Check for duplicate unit */ 751 LIST_FOREACH(gp, &mp->geom, geom) { 752 sc = gp->softc; 753 if (sc != NULL && sc->sc_unit == *unit) { 754 gctl_error(req, "Unit %d already configured", *unit); 755 return; 756 } 757 } 758 759 if (*nprovider <= 0) { 760 gctl_error(req, "Bogus nprovider argument (= %d)", *nprovider); 761 return; 762 } 763 764 /* Check all providers are valid */ 765 for (i = 0; i < *nprovider; i++) { 766 snprintf(buf, sizeof(buf), "provider%d", i); 767 pp = gctl_get_provider(req, buf); 768 if (pp == NULL) 769 return; 770 } 771 772 gp = g_new_geomf(mp, "ccd%d", *unit); 773 sc = g_malloc(sizeof *sc, M_WAITOK | M_ZERO); 774 gp->softc = sc; 775 sc->sc_ndisks = *nprovider; 776 777 /* Allocate space for the component info. */ 778 sc->sc_cinfo = g_malloc(sc->sc_ndisks * sizeof(struct ccdcinfo), 779 M_WAITOK | M_ZERO); 780 781 /* Create consumers and attach to all providers */ 782 for (i = 0; i < *nprovider; i++) { 783 snprintf(buf, sizeof(buf), "provider%d", i); 784 pp = gctl_get_provider(req, buf); 785 cp = g_new_consumer(gp); 786 error = g_attach(cp, pp); 787 KASSERT(error == 0, ("attach to %s failed", pp->name)); 788 sc->sc_cinfo[i].ci_consumer = cp; 789 sc->sc_cinfo[i].ci_provider = pp; 790 } 791 792 sc->sc_unit = *unit; 793 sc->sc_ileave = *ileave; 794 795 if (gctl_get_param(req, "no_offset", NULL)) 796 sc->sc_flags |= CCDF_NO_OFFSET; 797 if (gctl_get_param(req, "linux", NULL)) 798 sc->sc_flags |= CCDF_LINUX; 799 800 if (gctl_get_param(req, "uniform", NULL)) 801 sc->sc_flags |= CCDF_UNIFORM; 802 if (gctl_get_param(req, "mirror", NULL)) 803 sc->sc_flags |= CCDF_MIRROR; 804 805 if (sc->sc_ileave == 0 && (sc->sc_flags & CCDF_MIRROR)) { 806 printf("%s: disabling mirror, interleave is 0\n", gp->name); 807 sc->sc_flags &= ~(CCDF_MIRROR); 808 } 809 810 if ((sc->sc_flags & CCDF_MIRROR) && !(sc->sc_flags & CCDF_UNIFORM)) { 811 printf("%s: mirror/parity forces uniform flag\n", gp->name); 812 sc->sc_flags |= CCDF_UNIFORM; 813 } 814 815 error = ccdinit(req, sc); 816 if (error != 0) { 817 g_ccd_freesc(sc); 818 gp->softc = NULL; 819 g_wither_geom(gp, ENXIO); 820 return; 821 } 822 823 pp = g_new_providerf(gp, "%s", gp->name); 824 pp->mediasize = sc->sc_size * (off_t)sc->sc_secsize; 825 pp->sectorsize = sc->sc_secsize; 826 g_error_provider(pp, 0); 827 828 sb = sbuf_new_auto(); 829 sbuf_printf(sb, "ccd%d: %d components ", sc->sc_unit, *nprovider); 830 for (i = 0; i < *nprovider; i++) { 831 sbuf_printf(sb, "%s%s", 832 i == 0 ? "(" : ", ", 833 sc->sc_cinfo[i].ci_provider->name); 834 } 835 sbuf_printf(sb, "), %jd blocks ", (off_t)pp->mediasize / DEV_BSIZE); 836 if (sc->sc_ileave != 0) 837 sbuf_printf(sb, "interleaved at %d blocks\n", 838 sc->sc_ileave); 839 else 840 sbuf_printf(sb, "concatenated\n"); 841 sbuf_finish(sb); 842 gctl_set_param_err(req, "output", sbuf_data(sb), sbuf_len(sb) + 1); 843 sbuf_delete(sb); 844 } 845 846 static int 847 g_ccd_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp) 848 { 849 struct g_provider *pp; 850 struct ccd_s *sc; 851 852 g_topology_assert(); 853 sc = gp->softc; 854 pp = LIST_FIRST(&gp->provider); 855 if (sc == NULL || pp == NULL) 856 return (EBUSY); 857 if (pp->acr != 0 || pp->acw != 0 || pp->ace != 0) { 858 gctl_error(req, "%s is open(r%dw%de%d)", gp->name, 859 pp->acr, pp->acw, pp->ace); 860 return (EBUSY); 861 } 862 g_ccd_freesc(sc); 863 gp->softc = NULL; 864 g_wither_geom(gp, ENXIO); 865 return (0); 866 } 867 868 static void 869 g_ccd_list(struct gctl_req *req, struct g_class *mp) 870 { 871 struct sbuf *sb; 872 struct ccd_s *cs; 873 struct g_geom *gp; 874 int i, unit, *up; 875 876 up = gctl_get_paraml(req, "unit", sizeof (*up)); 877 if (up == NULL) { 878 gctl_error(req, "unit parameter not given"); 879 return; 880 } 881 unit = *up; 882 sb = sbuf_new_auto(); 883 LIST_FOREACH(gp, &mp->geom, geom) { 884 cs = gp->softc; 885 if (cs == NULL || (unit >= 0 && unit != cs->sc_unit)) 886 continue; 887 sbuf_printf(sb, "ccd%d\t\t%d\t%d\t", 888 cs->sc_unit, cs->sc_ileave, cs->sc_flags & CCDF_USERMASK); 889 890 for (i = 0; i < cs->sc_ndisks; ++i) { 891 sbuf_printf(sb, "%s/dev/%s", i == 0 ? "" : " ", 892 cs->sc_cinfo[i].ci_provider->name); 893 } 894 sbuf_printf(sb, "\n"); 895 } 896 sbuf_finish(sb); 897 gctl_set_param_err(req, "output", sbuf_data(sb), sbuf_len(sb) + 1); 898 sbuf_delete(sb); 899 } 900 901 static void 902 g_ccd_config(struct gctl_req *req, struct g_class *mp, char const *verb) 903 { 904 struct g_geom *gp; 905 906 g_topology_assert(); 907 if (!strcmp(verb, "create geom")) { 908 g_ccd_create(req, mp); 909 } else if (!strcmp(verb, "destroy geom")) { 910 gp = gctl_get_geom(req, mp, "geom"); 911 if (gp != NULL) 912 g_ccd_destroy_geom(req, mp, gp); 913 } else if (!strcmp(verb, "list")) { 914 g_ccd_list(req, mp); 915 } else { 916 gctl_error(req, "unknown verb"); 917 } 918 } 919 920 static struct g_class g_ccd_class = { 921 .name = "CCD", 922 .version = G_VERSION, 923 .ctlreq = g_ccd_config, 924 .destroy_geom = g_ccd_destroy_geom, 925 .start = g_ccd_start, 926 .orphan = g_ccd_orphan, 927 .access = g_ccd_access, 928 }; 929 930 DECLARE_GEOM_CLASS(g_ccd_class, g_ccd); 931 MODULE_VERSION(geom_ccd, 0); 932