summaryrefslogtreecommitdiff
path: root/sys/dev/ccd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ccd.c')
-rw-r--r--sys/dev/ccd.c171
1 files changed, 134 insertions, 37 deletions
diff --git a/sys/dev/ccd.c b/sys/dev/ccd.c
index 6d657fa7844..cab34525248 100644
--- a/sys/dev/ccd.c
+++ b/sys/dev/ccd.c
@@ -1,7 +1,8 @@
-/* $NetBSD: ccd.c,v 1.23 1996/01/07 22:03:28 thorpej Exp $ */
+/* $OpenBSD: ccd.c,v 1.6 1996/02/27 09:43:17 niklas Exp $ */
+/* $NetBSD: ccd.c,v 1.27 1996/02/11 18:04:01 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 +84,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 +113,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 +128,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 +160,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 +361,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",
+ cs->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 +396,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;
}
/*
@@ -526,10 +565,13 @@ ccdopen(dev, flags, fmt, p)
ccdgetdisklabel(dev);
/* Check that the partition exists. */
- if (part != RAW_PART && ((part > lp->d_npartitions) ||
- (lp->d_partitions[part].p_fstype == FS_UNUSED))) {
- error = ENXIO;
- goto done;
+ if (part != RAW_PART) {
+ if (((cs->sc_flags & CCDF_INITED) == 0) ||
+ ((part > lp->d_npartitions) ||
+ (lp->d_partitions[part].p_fstype == FS_UNUSED))) {
+ error = ENXIO;
+ goto done;
+ }
}
/* Prevent our unit from being unconfigured while open. */
@@ -647,7 +689,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 +716,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 +739,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 +792,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 +814,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 +836,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 +893,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 +914,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);
}
@@ -1089,7 +1186,7 @@ ccdioctl(dev, cmd, data, flag, p)
bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
/* Detatch the disk. */
- disk_detatch(&cs->sc_dkdev);
+ disk_detach(&cs->sc_dkdev);
/* This must be atomic. */
s = splhigh();