summaryrefslogtreecommitdiffstats
path: root/sys/geom/geom_ccd.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2003-04-14 08:49:54 +0000
committerphk <phk@FreeBSD.org>2003-04-14 08:49:54 +0000
commitc10cd4d964cdb50012421cb5d82c7e1ac7357fcf (patch)
treec87ecfa8ba65a2d2726125e109c8484f8719f077 /sys/geom/geom_ccd.c
parentda1c42b4c0ecd653522d657a51eec4ef70210524 (diff)
downloadFreeBSD-src-c10cd4d964cdb50012421cb5d82c7e1ac7357fcf.zip
FreeBSD-src-c10cd4d964cdb50012421cb5d82c7e1ac7357fcf.tar.gz
More correct patch: Only call biofinish if we have not already sent
any children down the mesh.
Diffstat (limited to 'sys/geom/geom_ccd.c')
-rw-r--r--sys/geom/geom_ccd.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/geom/geom_ccd.c b/sys/geom/geom_ccd.c
index 7dd43f9..9af6b4a 100644
--- a/sys/geom/geom_ccd.c
+++ b/sys/geom/geom_ccd.c
@@ -564,6 +564,7 @@ ccdstart(struct ccd_s *cs, struct bio *bp)
caddr_t addr;
daddr_t bn;
int err;
+ int sent;
/*
* Translate the partition-relative block number to an absolute.
@@ -574,11 +575,24 @@ ccdstart(struct ccd_s *cs, struct bio *bp)
* Allocate component buffers and fire off the requests
*/
addr = bp->bio_data;
+ sent = 0;
for (bcount = bp->bio_bcount; bcount > 0; bcount -= rcount) {
err = ccdbuffer(cbp, cs, bp, bn, addr, bcount);
if (err) {
printf("ccdbuffer error %d\n", err);
- biofinish(bp, NULL, err);
+ if (!sent)
+ biofinish(bp, NULL, err);
+ else {
+ /*
+ * XXX: maybe a race where the partners
+ * XXX: we sent already have been in
+ * XXX: ccdiodone(). Single-threaded g_down
+ * XXX: may protect against this.
+ */
+ bp->bio_resid -= bcount;
+ bp->bio_error = err;
+ bp->bio_flags |= BIO_ERROR;
+ }
return;
}
rcount = cbp[0]->cb_buf.bio_bcount;
@@ -596,6 +610,7 @@ ccdstart(struct ccd_s *cs, struct bio *bp)
if (cbp[0]->cb_buf.bio_cmd == BIO_WRITE) {
BIO_STRATEGY(&cbp[0]->cb_buf);
BIO_STRATEGY(&cbp[1]->cb_buf);
+ sent++;
} else {
int pick = cs->sc_pick;
daddr_t range = cs->sc_size / 16;
@@ -607,12 +622,14 @@ ccdstart(struct ccd_s *cs, struct bio *bp)
}
cs->sc_blk[pick] = bn + btodb(rcount);
BIO_STRATEGY(&cbp[pick]->cb_buf);
+ sent++;
}
} else {
/*
* Not mirroring
*/
BIO_STRATEGY(&cbp[0]->cb_buf);
+ sent++;
}
bn += btodb(rcount);
addr += rcount;
OpenPOWER on IntegriCloud