summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorasami <asami@FreeBSD.org>1996-03-26 02:29:11 +0000
committerasami <asami@FreeBSD.org>1996-03-26 02:29:11 +0000
commitb50b9c720907e35eb46b3c6216e7598e7bbc9e5c (patch)
tree78641bc63aa0eefdd59b130e0d6485ada28a13e5 /sys/geom
parenteae3c9253f3cfd2661f9304525e82035390da7f7 (diff)
downloadFreeBSD-src-b50b9c720907e35eb46b3c6216e7598e7bbc9e5c.zip
FreeBSD-src-b50b9c720907e35eb46b3c6216e7598e7bbc9e5c.tar.gz
Change how mirror writes are handled, according to the discussion on the
mailing list. When initiating a write, ccdbuffer() returns two "struct ccdbuf *"s linked together by the cb_mirror field. "cb_pflags & CCDPF_MIRROR_DONE" is set to 0 on both of them. When a component returns to ccdiodone(), it checks if "cb_pflags & CCDPF_MIRROR_DONE" is set or not. If not, it sets the partner's flag and returns. If it is, it means its partner has already returned, so it will go to the regular cleanup (which is in the fallthrough code). There should be no performance or functionality changes unless the higher-level scsi driver does something with the resid value. The change is purely aesthetical and prepares us for the parity implementation.
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/geom_ccd.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/sys/geom/geom_ccd.c b/sys/geom/geom_ccd.c
index dab208c..1601e89 100644
--- a/sys/geom/geom_ccd.c
+++ b/sys/geom/geom_ccd.c
@@ -1,4 +1,4 @@
-/* $Id: ccd.c,v 1.7 1996/01/31 11:25:46 asami Exp $ */
+/* $Id: ccd.c,v 1.8 1996/03/21 04:13:25 asami Exp $ */
/* $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ */
@@ -136,13 +136,32 @@ int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL | CCDB_VNODE;
#define ccdunit(x) dkunit(x)
#define ccdpart(x) dkpart(x)
+/*
+ This is how mirroring works (only writes are special):
+
+ When initiating a write, ccdbuffer() returns two "struct ccdbuf *"s
+ linked together by the cb_mirror field. "cb_pflags &
+ CCDPF_MIRROR_DONE" is set to 0 on both of them.
+
+ When a component returns to ccdiodone(), it checks if "cb_pflags &
+ CCDPF_MIRROR_DONE" is set or not. If not, it sets the partner's
+ flag and returns. If it is, it means its partner has already
+ returned, so it will go to the regular cleanup.
+
+ */
+
struct ccdbuf {
struct buf cb_buf; /* new I/O buf */
struct buf *cb_obp; /* ptr. to original I/O buf */
int cb_unit; /* target unit */
int cb_comp; /* target component */
+ int cb_pflags; /* mirror/parity status flag */
+ struct ccdbuf *cb_mirror; /* mirror counterpart */
};
+/* bits in cb_pflags */
+#define CCDPF_MIRROR_DONE 1 /* if set, mirror counterpart is done */
+
#define getccdbuf() \
((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK))
#define putccdbuf(cbp) \
@@ -703,10 +722,7 @@ ccdstrategy(bp)
if (bounds_check_with_label(bp, lp, wlabel) <= 0)
goto done;
- 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;
+ bp->b_resid = bp->b_bcount;
/*
* "Start" the unit.
@@ -896,6 +912,11 @@ ccdbuffer(cb, cs, bp, bn, addr, bcount)
cbp->cb_buf.b_vp = ci2->ci_vp;
cbp->cb_comp = ci2 - cs->sc_cinfo;
cb[1] = cbp;
+ /* link together the ccdbuf's and clear "mirror done" flag */
+ cb[0]->cb_mirror = cb[1];
+ cb[1]->cb_mirror = cb[0];
+ cb[0]->cb_pflags &= ~CCDPF_MIRROR_DONE;
+ cb[1]->cb_pflags &= ~CCDPF_MIRROR_DONE;
}
}
@@ -923,10 +944,7 @@ ccdintr(cs, bp)
dk_busy &= ~(1 << cs->sc_dk);
#endif
if (bp->b_flags & B_ERROR)
- 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;
+ bp->b_resid = bp->b_bcount;
biodone(bp);
}
@@ -965,6 +983,18 @@ ccdiodone(cbp)
unit, bp->b_error, cbp->cb_comp);
#endif
}
+
+ if (ccd_softc[unit].sc_cflags & CCDF_MIRROR &&
+ (cbp->cb_buf.b_flags & B_READ) == 0)
+ if ((cbp->cb_pflags & CCDPF_MIRROR_DONE) == 0) {
+ /* I'm done before my counterpart, so just set
+ partner's flag and return */
+ cbp->cb_mirror->cb_pflags |= CCDPF_MIRROR_DONE;
+ putccdbuf(cbp);
+ splx(s);
+ return;
+ }
+
count = cbp->cb_buf.b_bcount;
putccdbuf(cbp);
OpenPOWER on IntegriCloud