summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/softraid.c5
-rw-r--r--sys/dev/softraid_crypto.c277
-rw-r--r--sys/dev/softraidvar.h4
3 files changed, 168 insertions, 118 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index b03137755e2..408516f511e 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.96 2008/01/24 19:58:08 marco Exp $ */
+/* $OpenBSD: softraid.c,v 1.97 2008/01/29 23:25:02 marco Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
*
@@ -277,6 +277,7 @@ sr_put_ccb(struct sr_ccb *ccb)
ccb->ccb_wu = NULL;
ccb->ccb_state = SR_CCB_FREE;
ccb->ccb_target = -1;
+ ccb->ccb_opaque = NULL;
TAILQ_INSERT_TAIL(&sd->sd_ccb_freeq, ccb, ccb_link);
@@ -807,7 +808,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
break;
#if 0
case 'C':
- if (no_chunk != 1)
+ if (no_chunk < 2)
goto unwind;
strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name));
vol_size = ch_entry->src_meta.scm_coerced_size;
diff --git a/sys/dev/softraid_crypto.c b/sys/dev/softraid_crypto.c
index cf5fdaa0454..b85f51def16 100644
--- a/sys/dev/softraid_crypto.c
+++ b/sys/dev/softraid_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid_crypto.c,v 1.4 2008/01/27 15:02:28 marco Exp $ */
+/* $OpenBSD: softraid_crypto.c,v 1.5 2008/01/29 23:25:02 marco Exp $ */
/*
* Copyright (c) 2007 Ted Unangst <tedu@openbsd.org>
*
@@ -47,10 +47,12 @@
#include <dev/rndvar.h>
struct cryptop * sr_crypto_getcryptop(struct sr_workunit *, int);
-void * sr_crypto_putcryptop(struct cryptop *);
-int sr_crypto_rw2(struct cryptop *);
+void *sr_crypto_putcryptop(struct cryptop *);
+int sr_crypto_write(struct cryptop *);
+int sr_crypto_rw2(struct sr_workunit *, struct cryptop *);
void sr_crypto_intr(struct buf *);
-int sr_crypto_intr2(struct cryptop *);
+int sr_crypto_read(struct cryptop *);
+void sr_crypto_finish_io(struct sr_workunit *);
struct cryptop *
sr_crypto_getcryptop(struct sr_workunit *wu, int encrypt)
@@ -61,16 +63,22 @@ sr_crypto_getcryptop(struct sr_workunit *wu, int encrypt)
struct cryptodesc *crd;
struct uio *uio;
int flags, i, n;
- int blk = 0;
+ daddr64_t blk = 0;
DNPRINTF(SR_D_DIS, "%s: sr_crypto_getcryptop wu: %p encrypt: %d\n",
DEVNAME(sd->sd_sc), wu, encrypt);
- uio = malloc(sizeof(*uio), M_DEVBUF, M_WAITOK | M_ZERO);
- uio->uio_iov = malloc(sizeof(*uio->uio_iov), M_DEVBUF, M_WAITOK);
+ /* XXX eliminate all malloc here, make either pool or pre-alloc */
+ uio = malloc(sizeof(*uio), M_DEVBUF, M_NOWAIT | M_ZERO);
+ uio->uio_iov = malloc(sizeof(*uio->uio_iov), M_DEVBUF, M_NOWAIT);
uio->uio_iovcnt = 1;
- uio->uio_iov->iov_base = xs->data;
uio->uio_iov->iov_len = xs->datalen;
+ if (xs->flags & SCSI_DATA_OUT) {
+ uio->uio_iov->iov_base = malloc(xs->datalen, M_DEVBUF,
+ M_NOWAIT);
+ bcopy(xs->data, uio->uio_iov->iov_base, xs->datalen);
+ } else
+ uio->uio_iov->iov_base = xs->data;
if (xs->cmdlen == 10)
blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
@@ -84,6 +92,8 @@ sr_crypto_getcryptop(struct sr_workunit *wu, int encrypt)
CRD_F_IV_PRESENT | CRD_F_IV_EXPLICIT;
crp = crypto_getreq(n);
+ if (crp == NULL)
+ goto unwind;
crp->crp_sid = sd->mds.mdd_crypto.src_sid;
crp->crp_ilen = xs->datalen;
@@ -102,21 +112,30 @@ sr_crypto_getcryptop(struct sr_workunit *wu, int encrypt)
}
return (crp);
+unwind:
+ if (wu->swu_xs->flags & SCSI_DATA_OUT)
+ free(uio->uio_iov->iov_base, M_DEVBUF);
+ free(uio->uio_iov, M_DEVBUF);
+ free(uio, M_DEVBUF);
+ return (NULL);
}
void *
sr_crypto_putcryptop(struct cryptop *crp)
{
struct uio *uio = crp->crp_buf;
- void *opaque = crp->crp_opaque;
+ struct sr_workunit *wu = crp->crp_opaque;
- DNPRINTF(SR_D_DIS, "sr_crypto_putcryptop crp: %p\n", crp);
+ DNPRINTF(SR_D_DIS, "%s: sr_crypto_putcryptop crp: %p\n",
+ DEVNAME(wu->swu_dis->sd_sc), crp);
+ if (wu->swu_xs->flags & SCSI_DATA_OUT)
+ free(uio->uio_iov->iov_base, M_DEVBUF);
free(uio->uio_iov, M_DEVBUF);
free(uio, M_DEVBUF);
crypto_freereq(crp);
- return (opaque);
+ return (wu);
}
int
@@ -173,35 +192,71 @@ int
sr_crypto_rw(struct sr_workunit *wu)
{
struct cryptop *crp;
+ int s, rv = 0;
DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw wu: %p\n",
DEVNAME(wu->swu_dis->sd_sc), wu);
- crp = sr_crypto_getcryptop(wu, 1);
- crp->crp_callback = sr_crypto_rw2;
- crp->crp_opaque = wu;
- crypto_dispatch(crp);
+ if (wu->swu_xs->flags & SCSI_DATA_OUT) {
+ crp = sr_crypto_getcryptop(wu, 1);
+ crp->crp_callback = sr_crypto_write;
+ crp->crp_opaque = wu;
+ s = splvm();
+ if (crypto_invoke(crp))
+ rv = 1;
+ splx(s);
+ } else
+ rv = sr_crypto_rw2(wu, NULL);
- return (0);
+ return (rv);
+}
+
+int
+sr_crypto_write(struct cryptop *crp)
+{
+ int s;
+#ifdef SR_DEBUG
+ struct sr_workunit *wu = crp->crp_opaque;
+#endif /* SR_DEBUG */
+
+ DNPRINTF(SR_D_INTR, "%s: sr_crypto_write: wu %x xs: %x\n",
+ DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs);
+
+ if (crp->crp_etype) {
+ /* fail io */
+ ((struct sr_workunit *)(crp->crp_opaque))->swu_xs->error =
+ XS_DRIVER_STUFFUP;
+ s = splbio();
+ sr_crypto_finish_io(crp->crp_opaque);
+ splx(s);
+ }
+
+ return (sr_crypto_rw2(crp->crp_opaque, crp));
}
int
-sr_crypto_rw2(struct cryptop *crp)
+sr_crypto_rw2(struct sr_workunit *wu, struct cryptop *crp)
{
- struct sr_workunit *wu = sr_crypto_putcryptop(crp);
struct sr_discipline *sd = wu->swu_dis;
struct scsi_xfer *xs = wu->swu_xs;
struct sr_workunit *wup;
struct sr_ccb *ccb;
struct sr_chunk *scp;
- int s, rt;
+ struct uio *uio;
+ int s;
daddr64_t blk;
- DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw2 0x%02x\n", DEVNAME(sd->sd_sc),
- xs->cmd->opcode);
+ DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw2 wu: %p\n",
+ DEVNAME(sd->sd_sc), wu);
- if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
- DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw device offline\n",
+ if (sd->sd_vol.sv_meta.svm_status != BIOC_SVONLINE) {
+ DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw2 device offline\n",
+ DEVNAME(sd->sd_sc));
+ goto bad;
+ }
+ scp = sd->sd_vol.sv_chunks[0];
+ if (scp->src_meta.scm_status != BIOC_SDONLINE) {
+ DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw2 disk offline\n",
DEVNAME(sd->sd_sc));
goto bad;
}
@@ -228,8 +283,8 @@ sr_crypto_rw2(struct cryptop *crp)
wu->swu_blk_end = blk + (xs->datalen >> 9) - 1;
if (wu->swu_blk_end > sd->sd_vol.sv_meta.svm_size) {
- DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw2 out of bounds start: %lld "
- "end: %lld length: %d\n", wu->swu_blk_start,
+ DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw2 out of bounds "
+ "start: %lld end: %lld length: %d\n", wu->swu_blk_start,
wu->swu_blk_end, xs->datalen);
sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT |
@@ -255,68 +310,26 @@ sr_crypto_rw2(struct cryptop *crp)
goto bad;
}
- if (xs->flags & SCSI_POLL) {
- panic("not yet, crypto poll");
- ccb->ccb_buf.b_flags = 0;
- ccb->ccb_buf.b_iodone = NULL;
- } else {
- ccb->ccb_buf.b_flags = B_CALL;
- ccb->ccb_buf.b_iodone = sr_crypto_intr;
- }
-
+ ccb->ccb_buf.b_flags = B_CALL;
+ ccb->ccb_buf.b_iodone = sr_crypto_intr;
ccb->ccb_buf.b_blkno = blk;
ccb->ccb_buf.b_bcount = xs->datalen;
ccb->ccb_buf.b_bufsize = xs->datalen;
ccb->ccb_buf.b_resid = xs->datalen;
- ccb->ccb_buf.b_data = xs->data;
- ccb->ccb_buf.b_error = 0;
- ccb->ccb_buf.b_proc = curproc;
- ccb->ccb_wu = wu;
if (xs->flags & SCSI_DATA_IN) {
- rt = 0;
-ragain:
- scp = sd->sd_vol.sv_chunks[0];
- switch (scp->src_meta.scm_status) {
- case BIOC_SDONLINE:
- case BIOC_SDSCRUB:
- ccb->ccb_buf.b_flags |= B_READ;
- break;
-
- case BIOC_SDOFFLINE:
- case BIOC_SDREBUILD:
- case BIOC_SDHOTSPARE:
- if (rt++ < sd->sd_vol.sv_meta.svm_no_chunk)
- goto ragain;
-
- /* FALLTHROUGH */
- default:
- /* volume offline */
- printf("%s: is offline, can't read\n",
- DEVNAME(sd->sd_sc));
- sr_put_ccb(ccb);
- goto bad;
- }
+ ccb->ccb_buf.b_flags |= B_READ;
+ ccb->ccb_buf.b_data = xs->data;
} else {
- scp = sd->sd_vol.sv_chunks[0];
- switch (scp->src_meta.scm_status) {
- case BIOC_SDONLINE:
- case BIOC_SDSCRUB:
- case BIOC_SDREBUILD:
- ccb->ccb_buf.b_flags |= B_WRITE;
- break;
-
- case BIOC_SDHOTSPARE: /* should never happen */
- case BIOC_SDOFFLINE:
- wu->swu_io_count--;
- sr_put_ccb(ccb);
- goto bad;
-
- default:
- goto bad;
- }
-
+ uio = crp->crp_buf;
+ ccb->ccb_buf.b_flags |= B_WRITE;
+ ccb->ccb_buf.b_data = uio->uio_iov->iov_base;
+ ccb->ccb_opaque = crp;
}
+
+ ccb->ccb_buf.b_error = 0;
+ ccb->ccb_buf.b_proc = curproc;
+ ccb->ccb_wu = wu;
ccb->ccb_target = 0;
ccb->ccb_buf.b_dev = sd->sd_vol.sv_chunks[0]->src_dev_mm;
ccb->ccb_buf.b_vp = NULL;
@@ -325,7 +338,7 @@ ragain:
TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link);
- DNPRINTF(SR_D_DIS, "%s: %s: sr_crypto: b_bcount: %d "
+ DNPRINTF(SR_D_DIS, "%s: %s: sr_crypto_rw2: b_bcount: %d "
"b_blkno: %x b_flags 0x%0x b_data %p\n",
DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_blkno,
@@ -352,8 +365,6 @@ ragain:
goto queued;
}
- /* XXX deal with polling */
-
sr_raid_startwu(wu);
queued:
@@ -368,11 +379,12 @@ void
sr_crypto_intr(struct buf *bp)
{
struct sr_ccb *ccb = (struct sr_ccb *)bp;
- struct sr_workunit *wu = ccb->ccb_wu;
+ struct sr_workunit *wu = ccb->ccb_wu, *wup;
+ struct sr_discipline *sd = wu->swu_dis;
+ struct scsi_xfer *xs = wu->swu_xs;
+ struct sr_softc *sc = sd->sd_sc;
struct cryptop *crp;
-#ifdef SR_DEBUG
- struct sr_softc *sc = wu->swu_dis->sd_sc;
-#endif
+ int s, s2, pend;
DNPRINTF(SR_D_INTR, "%s: sr_crypto_intr bp: %x xs: %x\n",
DEVNAME(sc), bp, wu->swu_xs);
@@ -381,26 +393,6 @@ sr_crypto_intr(struct buf *bp)
" b_flags: 0x%0x\n", DEVNAME(sc), ccb->ccb_buf.b_bcount,
ccb->ccb_buf.b_resid, ccb->ccb_buf.b_flags);
- crp = sr_crypto_getcryptop(wu, 0);
- crp->crp_callback = sr_crypto_intr2;
- crp->crp_opaque = bp;
- crypto_dispatch(crp);
-}
-
-int
-sr_crypto_intr2(struct cryptop *crp)
-{
- struct buf *bp = sr_crypto_putcryptop(crp);
- struct sr_ccb *ccb = (struct sr_ccb *)bp;
- struct sr_workunit *wu = ccb->ccb_wu, *wup;
- struct sr_discipline *sd = wu->swu_dis;
- struct scsi_xfer *xs = wu->swu_xs;
- struct sr_softc *sc = sd->sd_sc;
- int s, pend;
-
- DNPRINTF(SR_D_INTR, "%s: sr_crypto_intr2 crp: %x xs: %x\n",
- DEVNAME(sc), crp, xs);
-
s = splbio();
if (ccb->ccb_buf.b_flags & B_ERROR) {
@@ -419,7 +411,7 @@ sr_crypto_intr2(struct cryptop *crp)
}
wu->swu_ios_complete++;
- DNPRINTF(SR_D_INTR, "%s: sr_crypto_intr2: comp: %d count: %d\n",
+ DNPRINTF(SR_D_INTR, "%s: sr_crypto_intr: comp: %d count: %d\n",
DEVNAME(sc), wu->swu_ios_complete, wu->swu_io_count);
if (wu->swu_ios_complete == wu->swu_io_count) {
@@ -428,9 +420,6 @@ sr_crypto_intr2(struct cryptop *crp)
else
xs->error = XS_NOERROR;
- xs->resid = 0;
- xs->flags |= ITSDONE;
-
pend = 0;
TAILQ_FOREACH(wup, &sd->sd_wu_pendq, swu_link) {
if (wu == wup) {
@@ -454,14 +443,72 @@ sr_crypto_intr2(struct cryptop *crp)
printf("%s: wu: %p not on pending queue\n",
DEVNAME(sc), wu);
- /* do not change the order of these 2 functions */
- sr_put_wu(wu);
- scsi_done(xs);
+ /* do this after restarting other wus to shorten latency */
+ if ((xs->flags & SCSI_DATA_IN) && (xs->error == XS_NOERROR)) {
+ crp = sr_crypto_getcryptop(wu, 0);
+ ccb->ccb_opaque = crp;
+ crp->crp_callback = sr_crypto_read;
+ crp->crp_opaque = wu;
+ DNPRINTF(SR_D_INTR, "%s: sr_crypto_intr: crypto_invoke "
+ "%p\n", DEVNAME(sc), crp);
+ s2 = splvm();
+ crypto_invoke(crp);
+ splx(s2);
+ goto done;
+ }
+
+ sr_crypto_finish_io(wu);
+ }
- if (sd->sd_sync && sd->sd_wu_pending == 0)
- wakeup(sd);
+done:
+ splx(s);
+}
+
+void
+sr_crypto_finish_io(struct sr_workunit *wu)
+{
+ struct sr_discipline *sd = wu->swu_dis;
+ struct scsi_xfer *xs = wu->swu_xs;
+ struct sr_ccb *ccb;
+#ifdef SR_DEBUG
+ struct sr_softc *sc = sd->sd_sc;
+#endif /* SR_DEBUG */
+ splassert(IPL_BIO);
+
+ DNPRINTF(SR_D_INTR, "%s: sr_crypto_finish_io: wu %x xs: %x\n",
+ DEVNAME(sc), wu, xs);
+
+ xs->resid = 0;
+ xs->flags |= ITSDONE;
+
+ TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) {
+ if (ccb->ccb_opaque == NULL)
+ continue;
+ sr_crypto_putcryptop(ccb->ccb_opaque);
}
+ /* do not change the order of these 2 functions */
+ sr_put_wu(wu);
+ scsi_done(xs);
+
+ if (sd->sd_sync && sd->sd_wu_pending == 0)
+ wakeup(sd);
+}
+
+int
+sr_crypto_read(struct cryptop *crp)
+{
+ int s;
+ struct sr_workunit *wu = crp->crp_opaque;
+
+ DNPRINTF(SR_D_INTR, "%s: sr_crypto_read: wu %x xs: %x\n",
+ DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs);
+
+ if (crp->crp_etype)
+ wu->swu_xs->error = XS_DRIVER_STUFFUP;
+
+ s = splbio();
+ sr_crypto_finish_io(crp->crp_opaque);
splx(s);
return (0);
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index b968c209c57..24a87d53bc0 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.39 2008/01/26 19:29:55 marco Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.40 2008/01/29 23:25:02 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -75,6 +75,8 @@ struct sr_ccb {
#define SR_CCB_OK 2
#define SR_CCB_FAILED 3
+ void *ccb_opaque; /* discipline usable pointer */
+
TAILQ_ENTRY(sr_ccb) ccb_link;
} __packed;