summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ccd.c157
-rw-r--r--sys/dev/ccdvar.h5
2 files changed, 128 insertions, 34 deletions
diff --git a/sys/dev/ccd.c b/sys/dev/ccd.c
index 6d657fa7844..32ee8dc3bf8 100644
--- a/sys/dev/ccd.c
+++ b/sys/dev/ccd.c
@@ -1,7 +1,7 @@
-/* $NetBSD: ccd.c,v 1.23 1996/01/07 22:03:28 thorpej Exp $ */
+/* $NetBSD: ccd.c,v 1.24 1996/02/01 20:47:13 thorpej Exp $ */
/*
- * Copyright (c) 1995 Jason R. Thorpe.
+ * Copyright (c) 1995, 1996 Jason R. Thorpe.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -83,6 +83,9 @@
* Mail Stop 258-6
* NASA Ames Research Center
* Moffett Field, CA 94035
+ *
+ * Mirroring support based on code written by Satoshi Asami
+ * and Nisha Talagala.
*/
#include <sys/param.h>
@@ -109,12 +112,12 @@
#endif
#ifdef DEBUG
-int ccddebug = 0x00;
#define CCDB_FOLLOW 0x01
#define CCDB_INIT 0x02
#define CCDB_IO 0x04
#define CCDB_LABEL 0x08
#define CCDB_VNODE 0x10
+int ccddebug = 0x00;
#endif
#define ccdunit(x) DISKUNIT(x)
@@ -124,6 +127,9 @@ struct ccdbuf {
struct buf *cb_obp; /* ptr. to original I/O buf */
int cb_unit; /* target unit */
int cb_comp; /* target component */
+ int cb_flags; /* misc. flags */
+
+#define CBF_MIRROR 0x01 /* we're for a mirror component */
};
#define getccdbuf() \
@@ -153,8 +159,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 ccd_softc *, struct buf *,
+ daddr_t, caddr_t, long, struct ccdbuf **));
static void ccdgetdisklabel __P((dev_t));
static void ccdmakedisklabel __P((struct ccd_softc *));
static int ccdlock __P((struct ccd_softc *));
@@ -354,6 +360,34 @@ ccdinit(ccd, cpaths, p)
}
/*
+ * Mirroring support requires uniform interleave and
+ * and even number of components.
+ */
+ if (ccd->ccd_flags & CCDF_MIRROR) {
+ ccd->ccd_flags |= CCDF_UNIFORM;
+ if (cs->sc_ileave == 0) {
+#ifdef DEBUG
+ if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
+ printf("%s: mirroring requires interleave\n",
+ sc->sc_xname);
+#endif
+ free(ci->ci_path, M_DEVBUF);
+ free(cs->sc_cinfo, M_DEVBUF);
+ return (EINVAL);
+ }
+ if (cs->sc_nccdisks % 2) {
+#ifdef DEBUG
+ if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
+ printf("%s: mirroring requires even # of components\n",
+ cs->sc_xname);
+#endif
+ free(ci->ci_path, M_DEVBUF);
+ free(cs->sc_cinfo, M_DEVBUF);
+ return (EINVAL);
+ }
+ }
+
+ /*
* If uniform interleave is desired set all sizes to that of
* the smallest component.
*/
@@ -361,7 +395,11 @@ ccdinit(ccd, cpaths, p)
for (ci = cs->sc_cinfo;
ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
ci->ci_size = minsize;
- cs->sc_size = cs->sc_nccdisks * minsize;
+
+ if (ccd->ccd_flags & CCDF_MIRROR)
+ cs->sc_size = (cs->sc_nccdisks / 2) * minsize;
+ else
+ cs->sc_size = cs->sc_nccdisks * minsize;
}
/*
@@ -647,7 +685,7 @@ ccdstart(cs, bp)
register struct buf *bp;
{
register long bcount, rcount;
- struct ccdbuf *cbp;
+ struct ccdbuf *cbp[4];
caddr_t addr;
daddr_t bn;
struct partition *pp;
@@ -674,11 +712,21 @@ 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(cs, bp, bn, addr, bcount, cbp);
+ 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);
+
+ /*
+ * Mirror requires additional write.
+ */
+ if ((cs->sc_cflags & CCDF_MIRROR) &&
+ ((cbp[0]->cb_buf.b_flags & B_READ) == 0)) {
+ cbp[1]->cb_buf.b_vp->v_numoutput++;
+ VOP_STRATEGY(&cbp[1]->cb_buf);
+ }
+
bn += btodb(rcount);
addr += rcount;
}
@@ -687,15 +735,16 @@ ccdstart(cs, bp)
/*
* Build a component buffer header.
*/
-static struct ccdbuf *
-ccdbuffer(cs, bp, bn, addr, bcount)
+static void
+ccdbuffer(cs, bp, bn, addr, bcount, cbpp)
register struct ccd_softc *cs;
struct buf *bp;
daddr_t bn;
caddr_t addr;
long bcount;
+ struct ccdbuf **cbpp;
{
- register struct ccdcinfo *ci;
+ register struct ccdcinfo *ci, *ci2;
register struct ccdbuf *cbp;
register daddr_t cbn, cboff;
@@ -739,8 +788,19 @@ ccdbuffer(cs, bp, bn, addr, bcount)
ccdisk = ii->ii_index[0];
cbn = ii->ii_startoff + off;
} else {
- ccdisk = ii->ii_index[off % ii->ii_ndisk];
- cbn = ii->ii_startoff + off / ii->ii_ndisk;
+ 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 {
+ /* Normal case. */
+ ccdisk = ii->ii_index[off % ii->ii_ndisk];
+ cbn = ii->ii_startoff + off / ii->ii_ndisk;
+ }
}
cbn *= cs->sc_ileave;
ci = &cs->sc_cinfo[ccdisk];
@@ -750,6 +810,7 @@ ccdbuffer(cs, bp, bn, addr, bcount)
* Fill in the component buf structure.
*/
cbp = getccdbuf();
+ cbp->cb_flags = 0;
cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
cbp->cb_buf.b_iodone = (void (*)())ccdiodone;
cbp->cb_buf.b_proc = bp->b_proc;
@@ -771,13 +832,30 @@ ccdbuffer(cs, bp, bn, addr, bcount)
cbp->cb_unit = cs - ccd_softc;
cbp->cb_comp = ci - cs->sc_cinfo;
+ /* First buffer is dealt with. */
+ cbpp[0] = cbp;
+
#ifdef DEBUG
if (ccddebug & CCDB_IO)
printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
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);
+
+ /*
+ * Mirrors have an additional write operation that is nearly
+ * identical to the first.
+ */
+ if ((cs->sc_cflags & CCDF_MIRROR) &&
+ ((cbp->cb_buf.b_flags & B_READ) == 0)) {
+ cbp = getccdbuf();
+ *cbp = *cbpp[0];
+ cbp->cb_flags = CBF_MIRROR;
+ cbp->cb_buf.b_dev = ci2->ci_dev; /* XXX */
+ cbp->cb_buf.b_vp = ci2->ci_vp;
+ cbp->cb_comp = ci2 - cs->sc_cinfo;
+ cbpp[1] = cbp;
+ }
}
static void
@@ -811,15 +889,19 @@ ccdiodone(cbp)
register struct buf *bp = cbp->cb_obp;
register int unit = cbp->cb_unit;
struct ccd_softc *cs = &ccd_softc[unit];
- int count, s;
+ int count, cbflags, s;
+ char *comptype;
s = splbio();
#ifdef DEBUG
if (ccddebug & CCDB_FOLLOW)
printf("ccdiodone(%x)\n", cbp);
if (ccddebug & CCDB_IO) {
- printf("ccdiodone: bp %x bcount %d resid %d\n",
- bp, bp->b_bcount, bp->b_resid);
+ if (cbp->cb_flags & CBF_MIRROR)
+ printf("ccdiodone: mirror component\n");
+ else
+ printf("ccdiodone: bp %x bcount %d resid %d\n",
+ bp, bp->b_bcount, bp->b_resid);
printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
cbp->cb_buf.b_dev, cbp->cb_comp, cbp,
cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,
@@ -828,24 +910,35 @@ ccdiodone(cbp)
#endif
if (cbp->cb_buf.b_flags & B_ERROR) {
- bp->b_flags |= B_ERROR;
- bp->b_error = cbp->cb_buf.b_error ? cbp->cb_buf.b_error : EIO;
-#ifdef DEBUG
- printf("%s: error %d on component %d\n",
- cs->sc_xname, bp->b_error, cbp->cb_comp);
-#endif
+ if (cbp->cb_flags & CBF_MIRROR)
+ comptype = " (mirror)";
+ else {
+ bp->b_flags |= B_ERROR;
+ bp->b_error = cbp->cb_buf.b_error ?
+ cbp->cb_buf.b_error : EIO;
+ comptype = "";
+ }
+
+ printf("%s: error %d on component %d%s\n",
+ cs->sc_xname, bp->b_error, cbp->cb_comp, comptype);
}
count = cbp->cb_buf.b_bcount;
+ cbflags = cbp->cb_flags;
putccdbuf(cbp);
/*
* If all done, "interrupt".
+ *
+ * Note that mirror component buffers aren't counted against
+ * the original I/O buffer.
*/
- bp->b_resid -= count;
- if (bp->b_resid < 0)
- panic("ccdiodone: count");
- if (bp->b_resid == 0)
- ccdintr(&ccd_softc[unit], bp);
+ if ((cbflags & CBF_MIRROR) == 0) {
+ bp->b_resid -= count;
+ if (bp->b_resid < 0)
+ panic("ccdiodone: count");
+ if (bp->b_resid == 0)
+ ccdintr(&ccd_softc[unit], bp);
+ }
splx(s);
}
diff --git a/sys/dev/ccdvar.h b/sys/dev/ccdvar.h
index 0c10ecbccab..57fa84b30f2 100644
--- a/sys/dev/ccdvar.h
+++ b/sys/dev/ccdvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ccdvar.h,v 1.9 1996/01/07 22:03:30 thorpej Exp $ */
+/* $NetBSD: ccdvar.h,v 1.10 1996/02/01 20:47:26 thorpej Exp $ */
/*
* Copyright (c) 1995 Jason R. Thorpe.
@@ -110,9 +110,10 @@ struct ccd_ioctl {
/* ccd_flags */
#define CCDF_SWAP 0x01 /* interleave should be dmmax */
#define CCDF_UNIFORM 0x02 /* use LCCD of sizes for uniform interleave */
+#define CCDF_MIRROR 0x04 /* enable data mirroring */
/* Mask of user-settable ccd flags. */
-#define CCDF_USERMASK (CCDF_SWAP|CCDF_UNIFORM)
+#define CCDF_USERMASK (CCDF_SWAP|CCDF_UNIFORM|CCDF_MIRROR)
/*
* Component info table.