diff options
author | asami <asami@FreeBSD.org> | 1996-01-31 03:28:21 +0000 |
---|---|---|
committer | asami <asami@FreeBSD.org> | 1996-01-31 03:28:21 +0000 |
commit | 565f8b69877e3f3e95acb572ea163201ace4aa3f (patch) | |
tree | aff7eaf735ac04e3f08f634870421d22101bf70f /sys/dev | |
parent | 78108c6c2fff0fe74a09fa9d0322852075446a13 (diff) | |
download | FreeBSD-src-565f8b69877e3f3e95acb572ea163201ace4aa3f.zip FreeBSD-src-565f8b69877e3f3e95acb572ea163201ace4aa3f.tar.gz |
Mirror support. When CCDF_MIRROR is set:
(1) The reads are always done from the first n/2 disks.
(2) Each write is done twice, to the "data" disk (in the first half) and
the "mirror" disk (in the second half).
ccdbuffer() now takes an extra argument (struct ccdbuf **) and stores
the pointer to ccdbuf in there. In case of a mirrored write, it
allocates and stores two pointers. The "residual" is also doubled
for mirrored writes so that ccdiodone() can correctly tell when all
the writes are done.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ccd/ccd.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/sys/dev/ccd/ccd.c b/sys/dev/ccd/ccd.c index 66e5b28..c6b349c 100644 --- a/sys/dev/ccd/ccd.c +++ b/sys/dev/ccd/ccd.c @@ -1,4 +1,4 @@ -/* $Id: ccd.c,v 1.4 1996/01/02 23:32:54 asami Exp $ */ +/* $Id: ccd.c,v 1.5 1996/01/30 22:34:53 asami Exp $ */ /* $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ */ @@ -166,8 +166,8 @@ static void ccdinterleave __P((struct ccd_softc *, int)); static void ccdintr __P((struct ccd_softc *, struct buf *)); static int ccdinit __P((struct ccddevice *, char **, struct proc *)); static int ccdlookup __P((char *, struct proc *p, struct vnode **)); -static struct ccdbuf *ccdbuffer __P((struct ccd_softc *, struct buf *, - daddr_t, caddr_t, long)); +static void ccdbuffer __P((struct ccdbuf **ret, struct ccd_softc *, + struct buf *, daddr_t, caddr_t, long)); static void ccdgetdisklabel __P((dev_t)); static void ccdmakedisklabel __P((struct ccd_softc *)); static int ccdlock __P((struct ccd_softc *)); @@ -701,7 +701,10 @@ ccdstrategy(bp) if (bounds_check_with_label(bp, lp, wlabel) <= 0) goto done; - bp->b_resid = bp->b_bcount; + if (cs->sc_cflags & CCDF_MIRROR && (bp->b_flags & B_READ) == 0) + bp->b_resid = bp->b_bcount*2; + else + bp->b_resid = bp->b_bcount; /* * "Start" the unit. @@ -720,7 +723,8 @@ ccdstart(cs, bp) register struct buf *bp; { register long bcount, rcount; - struct ccdbuf *cbp; + struct ccdbuf *cbp[4]; + /* XXX! : 2 reads and 2 writes for RAID 4/5 */ caddr_t addr; daddr_t bn; struct partition *pp; @@ -756,11 +760,17 @@ ccdstart(cs, bp) */ addr = bp->b_data; for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { - cbp = ccdbuffer(cs, bp, bn, addr, bcount); - rcount = cbp->cb_buf.b_bcount; - if ((cbp->cb_buf.b_flags & B_READ) == 0) - cbp->cb_buf.b_vp->v_numoutput++; - VOP_STRATEGY(&cbp->cb_buf); + ccdbuffer(cbp, cs, bp, bn, addr, bcount); + rcount = cbp[0]->cb_buf.b_bcount; + if ((cbp[0]->cb_buf.b_flags & B_READ) == 0) + cbp[0]->cb_buf.b_vp->v_numoutput++; + VOP_STRATEGY(&cbp[0]->cb_buf); + if (cs->sc_cflags & CCDF_MIRROR && + (cbp[0]->cb_buf.b_flags & B_READ) == 0) { + /* mirror, start another write */ + cbp[1]->cb_buf.b_vp->v_numoutput++; + VOP_STRATEGY(&cbp[1]->cb_buf); + } bn += btodb(rcount); addr += rcount; } @@ -769,15 +779,16 @@ ccdstart(cs, bp) /* * Build a component buffer header. */ -static struct ccdbuf * -ccdbuffer(cs, bp, bn, addr, bcount) +void +ccdbuffer(cb, cs, bp, bn, addr, bcount) + register struct ccdbuf **cb; register struct ccd_softc *cs; struct buf *bp; daddr_t bn; caddr_t addr; long bcount; { - register struct ccdcinfo *ci; + register struct ccdcinfo *ci, *ci2; register struct ccdbuf *cbp; register daddr_t cbn, cboff; @@ -824,6 +835,8 @@ ccdbuffer(cs, bp, bn, addr, bcount) if (cs->sc_cflags & CCDF_MIRROR) { ccdisk = ii->ii_index[off % (ii->ii_ndisk/2)]; cbn = ii->ii_startoff + off / (ii->ii_ndisk/2); + /* mirrored data */ + ci2 = &cs->sc_cinfo[ccdisk + ii->ii_ndisk/2]; } else if (cs->sc_cflags & CCDF_PARITY) { ccdisk = ii->ii_index[off % (ii->ii_ndisk-1)]; @@ -871,7 +884,17 @@ ccdbuffer(cs, bp, bn, addr, bcount) ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, cbp->cb_buf.b_bcount); #endif - return (cbp); + cb[0] = cbp; + if (cs->sc_cflags & CCDF_MIRROR && + (cbp->cb_buf.b_flags & B_READ) == 0) { + /* mirror, start one more write */ + cbp = getccdbuf(); + *cbp = *cb[0]; + cbp->cb_buf.b_dev = ci2->ci_dev; + cbp->cb_buf.b_vp = ci2->ci_vp; + cbp->cb_comp = ci2 - cs->sc_cinfo; + cb[1] = cbp; + } } static void @@ -898,7 +921,10 @@ ccdintr(cs, bp) dk_busy &= ~(1 << cs->sc_dk); #endif if (bp->b_flags & B_ERROR) - bp->b_resid = bp->b_bcount; + if (cs->sc_cflags & CCDF_MIRROR && (bp->b_flags & B_READ) == 0) + bp->b_resid = bp->b_bcount*2; + else + bp->b_resid = bp->b_bcount; biodone(bp); } |