summaryrefslogtreecommitdiff
path: root/sys/dev/ccd.c
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>1996-02-01 20:47:13 +0000
committerthorpej <thorpej@NetBSD.org>1996-02-01 20:47:13 +0000
commit732dd94a83d574b6f98c06118d971237ab785dbc (patch)
treeea1c278ffb139808c08ed15aaf6df50b8e1208af /sys/dev/ccd.c
parent7b194ded9838c0ae9f829477095196dab027a4c9 (diff)
Add experimental data mirroring support, derived from code written by
Satoshi Asami and Nisha Talagala. For details on using data mirroring, see the ccd(4) manual page.
Diffstat (limited to 'sys/dev/ccd.c')
-rw-r--r--sys/dev/ccd.c157
1 files changed, 125 insertions, 32 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);
}