Lines Matching +full:non +full:- +full:interleaved

1 /*-
2 * SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause)
4 * Copyright (c) 2003 Poul-Henning Kamp.
35 /*-
75 * Mail Stop 258-6
104 /* Mask of user-settable ccd flags. */
109 * Computed at boot time to speed irregular-interleave lookups.
113 * remaining disks up to the size of the next-smallest (second group),
118 * three components of 5, 3, and 7 DEV_BSIZE blocks interleaved at
125 * 0 - - -
127 * which says that the first nine blocks (0-8) are interleaved over
129 * the next 4 blocks (9-12) are interleaved over 2 disks (0, 2) starting
130 * at component block 3, and the remaining blocks (13-14) are on disk
134 int ii_ndisk; /* # of disks range is interleaved over */
197 gp = pp->geom; in g_ccd_access()
199 LIST_FOREACH(cp1, &gp->consumer, consumer) { in g_ccd_access()
202 LIST_FOREACH(cp2, &gp->consumer, consumer) { in g_ccd_access()
205 g_access(cp2, -dr, -dw, -de); in g_ccd_access()
221 g_free(sc->sc_cinfo); in g_ccd_freesc()
222 if (sc->sc_itable != NULL) { in g_ccd_freesc()
223 for (ii = sc->sc_itable; ii->ii_ndisk > 0; ii++) in g_ccd_freesc()
224 g_free(ii->ii_index); in g_ccd_freesc()
225 g_free(sc->sc_itable); in g_ccd_freesc()
241 cs->sc_size = 0; in ccdinit()
246 if (cs->sc_flags & CCDF_LINUX) { in ccdinit()
247 cs->sc_offset = 0; in ccdinit()
248 cs->sc_ileave *= 2; in ccdinit()
249 if (cs->sc_flags & CCDF_MIRROR && cs->sc_ndisks != 2) in ccdinit()
253 if (cs->sc_flags & CCDF_NO_OFFSET) in ccdinit()
254 cs->sc_offset = 0; in ccdinit()
256 cs->sc_offset = CCD_OFFSET; in ccdinit()
258 for (ix = 0; ix < cs->sc_ndisks; ix++) { in ccdinit()
259 ci = &cs->sc_cinfo[ix]; in ccdinit()
261 mediasize = ci->ci_provider->mediasize; in ccdinit()
262 sectorsize = ci->ci_provider->sectorsize; in ccdinit()
265 size = mediasize / DEV_BSIZE - cs->sc_offset; in ccdinit()
269 if (cs->sc_ileave > 1) in ccdinit()
270 size -= size % cs->sc_ileave; in ccdinit()
274 ci->ci_provider->name); in ccdinit()
280 ci->ci_size = size; in ccdinit()
281 cs->sc_size += size; in ccdinit()
288 if ((cs->sc_ileave > 0) && in ccdinit()
289 (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { in ccdinit()
303 if (cs->sc_flags & CCDF_UNIFORM) { in ccdinit()
304 for (ix = 0; ix < cs->sc_ndisks; ix++) { in ccdinit()
305 ci = &cs->sc_cinfo[ix]; in ccdinit()
306 ci->ci_size = minsize; in ccdinit()
308 cs->sc_size = cs->sc_ndisks * minsize; in ccdinit()
311 if (cs->sc_flags & CCDF_MIRROR) { in ccdinit()
315 * be non-zero in order for us to be able to in ccdinit()
318 if (cs->sc_ndisks % 2) { in ccdinit()
323 if (cs->sc_ileave == 0) { in ccdinit()
328 cs->sc_size = (cs->sc_ndisks/2) * minsize; in ccdinit()
337 * Create pseudo-geometry based on 1MB cylinders. It's in ccdinit()
340 cs->sc_secsize = maxsecsize; in ccdinit()
361 size = (cs->sc_ndisks + 1) * sizeof(struct ccdiinfo); in ccdinterleave()
362 cs->sc_itable = g_malloc(size, M_WAITOK | M_ZERO); in ccdinterleave()
370 if (cs->sc_ileave == 0) { in ccdinterleave()
372 ii = cs->sc_itable; in ccdinterleave()
374 for (ix = 0; ix < cs->sc_ndisks; ix++) { in ccdinterleave()
376 ii->ii_index = g_malloc(sizeof(int), M_WAITOK); in ccdinterleave()
377 ii->ii_ndisk = 1; in ccdinterleave()
378 ii->ii_startblk = bn; in ccdinterleave()
379 ii->ii_startoff = 0; in ccdinterleave()
380 ii->ii_index[0] = ix; in ccdinterleave()
381 bn += cs->sc_cinfo[ix].ci_size; in ccdinterleave()
384 ii->ii_ndisk = 0; in ccdinterleave()
393 for (ii = cs->sc_itable; ; ii++) { in ccdinterleave()
398 ii->ii_index = g_malloc((sizeof(int) * cs->sc_ndisks), in ccdinterleave()
405 for (ci = cs->sc_cinfo; ci < &cs->sc_cinfo[cs->sc_ndisks]; in ccdinterleave()
407 if (ci->ci_size > size && in ccdinterleave()
409 ci->ci_size < smallci->ci_size)) { in ccdinterleave()
418 ii->ii_ndisk = 0; in ccdinterleave()
419 g_free(ii->ii_index); in ccdinterleave()
420 ii->ii_index = NULL; in ccdinterleave()
427 ii->ii_startblk = bn / cs->sc_ileave; in ccdinterleave()
434 ii->ii_startoff = lbn; in ccdinterleave()
441 for (ci = cs->sc_cinfo; in ccdinterleave()
442 ci < &cs->sc_cinfo[cs->sc_ndisks]; ci++) { in ccdinterleave()
443 if (ci->ci_size >= smallci->ci_size) { in ccdinterleave()
444 ii->ii_index[ix++] = ci - cs->sc_cinfo; in ccdinterleave()
447 ii->ii_ndisk = ix; in ccdinterleave()
448 bn += ix * (smallci->ci_size - size); in ccdinterleave()
449 lbn = smallci->ci_size / cs->sc_ileave; in ccdinterleave()
450 size = smallci->ci_size; in ccdinterleave()
464 cs = bp->bio_to->geom->softc; in g_ccd_start()
471 if(bp->bio_cmd == BIO_GETATTR) { in g_ccd_start()
477 * Translate the partition-relative block number to an absolute. in g_ccd_start()
479 bn = bp->bio_offset / cs->sc_secsize; in g_ccd_start()
484 addr = bp->bio_data; in g_ccd_start()
485 for (bcount = bp->bio_length; bcount > 0; bcount -= rcount) { in g_ccd_start()
488 bp->bio_completed += bcount; in g_ccd_start()
489 if (bp->bio_error == 0) in g_ccd_start()
490 bp->bio_error = err; in g_ccd_start()
491 if (bp->bio_completed == bp->bio_length) in g_ccd_start()
492 g_io_deliver(bp, bp->bio_error); in g_ccd_start()
495 rcount = cbp[0]->bio_length; in g_ccd_start()
497 if (cs->sc_flags & CCDF_MIRROR) { in g_ccd_start()
507 if (cbp[0]->bio_cmd != BIO_READ) { in g_ccd_start()
508 g_io_request(cbp[0], cbp[0]->bio_from); in g_ccd_start()
509 g_io_request(cbp[1], cbp[1]->bio_from); in g_ccd_start()
511 int pick = cs->sc_pick; in g_ccd_start()
512 daddr_t range = cs->sc_size / 16; in g_ccd_start()
514 if (bn < cs->sc_blk[pick] - range || in g_ccd_start()
515 bn > cs->sc_blk[pick] + range in g_ccd_start()
517 cs->sc_pick = pick = 1 - pick; in g_ccd_start()
519 cs->sc_blk[pick] = bn + btodb(rcount); in g_ccd_start()
520 g_io_request(cbp[pick], cbp[pick]->bio_from); in g_ccd_start()
526 g_io_request(cbp[0], cbp[0]->bio_from); in g_ccd_start()
550 if (cs->sc_ileave == 0) { in ccdbuffer()
558 for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++) in ccdbuffer()
559 sblk += ci->ci_size; in ccdbuffer()
560 cbn -= sblk; in ccdbuffer()
570 cboff = cbn % cs->sc_ileave; /* DEV_BSIZE gran */ in ccdbuffer()
571 cbn = cbn / cs->sc_ileave; /* DEV_BSIZE * ileave gran */ in ccdbuffer()
576 for (ii = cs->sc_itable; ii->ii_ndisk; ii++) { in ccdbuffer()
577 if (ii->ii_startblk > cbn) in ccdbuffer()
580 ii--; in ccdbuffer()
586 off = cbn - ii->ii_startblk; in ccdbuffer()
592 * adding 'off' and ii->ii_startoff together. However, 'off' in ccdbuffer()
595 * CCD-relative logical superblock number to a in ccdbuffer()
596 * component-relative superblock number. in ccdbuffer()
598 if (ii->ii_ndisk == 1) { in ccdbuffer()
603 ccdisk = ii->ii_index[0]; in ccdbuffer()
604 cbn = ii->ii_startoff + off; in ccdbuffer()
606 if (cs->sc_flags & CCDF_MIRROR) { in ccdbuffer()
619 int ndisk2 = ii->ii_ndisk / 2; in ccdbuffer()
620 ccdisk = ii->ii_index[off % ndisk2]; in ccdbuffer()
621 cbn = ii->ii_startoff + off / ndisk2; in ccdbuffer()
622 ci2 = &cs->sc_cinfo[ccdisk + ndisk2]; in ccdbuffer()
624 ccdisk = ii->ii_index[off % ii->ii_ndisk]; in ccdbuffer()
625 cbn = ii->ii_startoff + off / ii->ii_ndisk; in ccdbuffer()
629 ci = &cs->sc_cinfo[ccdisk]; in ccdbuffer()
636 cbn *= cs->sc_ileave; in ccdbuffer()
645 cbp->bio_done = g_std_done; in ccdbuffer()
646 cbp->bio_offset = dbtob(cbn + cboff + cs->sc_offset); in ccdbuffer()
647 cbp->bio_data = addr; in ccdbuffer()
648 if (cs->sc_ileave == 0) in ccdbuffer()
649 cbc = dbtob((off_t)(ci->ci_size - cbn)); in ccdbuffer()
651 cbc = dbtob((off_t)(cs->sc_ileave - cboff)); in ccdbuffer()
652 cbp->bio_length = (cbc < bcount) ? cbc : bcount; in ccdbuffer()
654 cbp->bio_from = ci->ci_consumer; in ccdbuffer()
657 if (cs->sc_flags & CCDF_MIRROR) { in ccdbuffer()
661 cbp->bio_done = cb[0]->bio_done = ccdiodone; in ccdbuffer()
662 cbp->bio_offset = cb[0]->bio_offset; in ccdbuffer()
663 cbp->bio_data = cb[0]->bio_data; in ccdbuffer()
664 cbp->bio_length = cb[0]->bio_length; in ccdbuffer()
665 cbp->bio_from = ci2->ci_consumer; in ccdbuffer()
666 cbp->bio_caller1 = cb[0]; in ccdbuffer()
667 cb[0]->bio_caller1 = cbp; in ccdbuffer()
681 mbp = cbp->bio_caller1; in ccdiodone()
682 pbp = cbp->bio_parent; in ccdiodone()
684 if (pbp->bio_cmd == BIO_READ) { in ccdiodone()
685 if (cbp->bio_error == 0) { in ccdiodone()
688 pbp->bio_inbed++; in ccdiodone()
696 mbp->bio_caller1 = NULL; in ccdiodone()
697 pbp->bio_inbed++; in ccdiodone()
699 g_io_request(mbp, mbp->bio_from); in ccdiodone()
710 mbp->bio_caller1 = NULL; in ccdiodone()
711 pbp->bio_inbed++; in ccdiodone()
712 if (cbp->bio_error != 0 && pbp->bio_error == 0) in ccdiodone()
713 pbp->bio_error = cbp->bio_error; in ccdiodone()
750 LIST_FOREACH(gp, &mp->geom, geom) { in g_ccd_create()
751 sc = gp->softc; in g_ccd_create()
752 if (sc != NULL && sc->sc_unit == *unit) { in g_ccd_create()
773 gp->softc = sc; in g_ccd_create()
774 sc->sc_ndisks = *nprovider; in g_ccd_create()
777 sc->sc_cinfo = g_malloc(sc->sc_ndisks * sizeof(struct ccdcinfo), in g_ccd_create()
786 KASSERT(error == 0, ("attach to %s failed", pp->name)); in g_ccd_create()
787 sc->sc_cinfo[i].ci_consumer = cp; in g_ccd_create()
788 sc->sc_cinfo[i].ci_provider = pp; in g_ccd_create()
791 sc->sc_unit = *unit; in g_ccd_create()
792 sc->sc_ileave = *ileave; in g_ccd_create()
795 sc->sc_flags |= CCDF_NO_OFFSET; in g_ccd_create()
797 sc->sc_flags |= CCDF_LINUX; in g_ccd_create()
800 sc->sc_flags |= CCDF_UNIFORM; in g_ccd_create()
802 sc->sc_flags |= CCDF_MIRROR; in g_ccd_create()
804 if (sc->sc_ileave == 0 && (sc->sc_flags & CCDF_MIRROR)) { in g_ccd_create()
805 printf("%s: disabling mirror, interleave is 0\n", gp->name); in g_ccd_create()
806 sc->sc_flags &= ~(CCDF_MIRROR); in g_ccd_create()
809 if ((sc->sc_flags & CCDF_MIRROR) && !(sc->sc_flags & CCDF_UNIFORM)) { in g_ccd_create()
810 printf("%s: mirror/parity forces uniform flag\n", gp->name); in g_ccd_create()
811 sc->sc_flags |= CCDF_UNIFORM; in g_ccd_create()
817 gp->softc = NULL; in g_ccd_create()
822 pp = g_new_providerf(gp, "%s", gp->name); in g_ccd_create()
823 pp->mediasize = sc->sc_size * (off_t)sc->sc_secsize; in g_ccd_create()
824 pp->sectorsize = sc->sc_secsize; in g_ccd_create()
828 sbuf_printf(sb, "ccd%d: %d components ", sc->sc_unit, *nprovider); in g_ccd_create()
832 sc->sc_cinfo[i].ci_provider->name); in g_ccd_create()
834 sbuf_printf(sb, "), %jd blocks ", (off_t)pp->mediasize / DEV_BSIZE); in g_ccd_create()
835 if (sc->sc_ileave != 0) in g_ccd_create()
836 sbuf_printf(sb, "interleaved at %d blocks\n", in g_ccd_create()
837 sc->sc_ileave); in g_ccd_create()
852 sc = gp->softc; in g_ccd_destroy_geom()
853 pp = LIST_FIRST(&gp->provider); in g_ccd_destroy_geom()
856 if (pp->acr != 0 || pp->acw != 0 || pp->ace != 0) { in g_ccd_destroy_geom()
857 gctl_error(req, "%s is open(r%dw%de%d)", gp->name, in g_ccd_destroy_geom()
858 pp->acr, pp->acw, pp->ace); in g_ccd_destroy_geom()
862 gp->softc = NULL; in g_ccd_destroy_geom()
882 LIST_FOREACH(gp, &mp->geom, geom) { in g_ccd_list()
883 cs = gp->softc; in g_ccd_list()
884 if (cs == NULL || (unit >= 0 && unit != cs->sc_unit)) in g_ccd_list()
887 cs->sc_unit, cs->sc_ileave, cs->sc_flags & CCDF_USERMASK); in g_ccd_list()
889 for (i = 0; i < cs->sc_ndisks; ++i) { in g_ccd_list()
891 cs->sc_cinfo[i].ci_provider->name); in g_ccd_list()