summaryrefslogtreecommitdiffstats
path: root/sys/dev/softraid.c
diff options
context:
space:
mode:
authortedu <tedu@openbsd.org>2007-05-30 13:55:47 +0000
committertedu <tedu@openbsd.org>2007-05-30 13:55:47 +0000
commited078b947550d68b9b3939e616affd56bae92773 (patch)
treecff7a22bfda2874103f6e7bb5f835374ef15550f /sys/dev/softraid.c
parentdocument \&$Mdocdate$; prodded by xsa (diff)
downloadwireguard-openbsd-ed078b947550d68b9b3939e616affd56bae92773.tar.xz
wireguard-openbsd-ed078b947550d68b9b3939e616affd56bae92773.zip
add basic support for a crypto(9) backed raid C discipline
ok marco
Diffstat (limited to 'sys/dev/softraid.c')
-rw-r--r--sys/dev/softraid.c494
1 files changed, 453 insertions, 41 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index 84af7ae27a2..222a807e7fc 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.57 2007/05/29 23:20:02 marco Exp $ */
+/* $OpenBSD: softraid.c,v 1.58 2007/05/30 13:55:47 tedu Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
*
@@ -34,6 +34,9 @@
#include <sys/sensors.h>
#include <sys/stat.h>
#include <sys/conf.h>
+#include <sys/uio.h>
+
+#include <crypto/cryptodev.h>
#include <machine/bus.h>
@@ -109,21 +112,30 @@ struct sr_workunit *sr_get_wu(struct sr_discipline *);
void sr_put_wu(struct sr_workunit *);
/* discipline functions */
+int sr_raid_inquiry(struct sr_workunit *);
+int sr_raid_read_cap(struct sr_workunit *);
+int sr_raid_tur(struct sr_workunit *);
+int sr_raid_request_sense( struct sr_workunit *);
+int sr_raid_start_stop(struct sr_workunit *);
+int sr_raid_sync(struct sr_workunit *);
+void sr_raid_set_chunk_state(struct sr_discipline *,
+ int, int);
+void sr_raid_set_vol_state(struct sr_discipline *);
+void sr_raid_startwu(struct sr_workunit *);
+
int sr_raid1_alloc_resources(struct sr_discipline *);
int sr_raid1_free_resources(struct sr_discipline *);
-
int sr_raid1_rw(struct sr_workunit *);
-int sr_raid1_inquiry(struct sr_workunit *);
-int sr_raid1_read_cap(struct sr_workunit *);
-int sr_raid1_tur(struct sr_workunit *);
-int sr_raid1_request_sense( struct sr_workunit *);
-int sr_raid1_start_stop(struct sr_workunit *);
-int sr_raid1_sync(struct sr_workunit *);
void sr_raid1_intr(struct buf *);
-void sr_raid1_set_chunk_state(struct sr_discipline *,
- int, int);
-void sr_raid1_set_vol_state(struct sr_discipline *);
-void sr_raid1_startwu(struct sr_workunit *);
+
+struct cryptop * sr_raidc_getcryptop(struct sr_workunit *, int);
+void * sr_raidc_putcryptop(struct cryptop *);
+int sr_raidc_alloc_resources(struct sr_discipline *);
+int sr_raidc_free_resources(struct sr_discipline *);
+int sr_raidc_rw(struct sr_workunit *);
+int sr_raidc_rw2(struct cryptop *);
+void sr_raidc_intr(struct buf *);
+int sr_raidc_intr2(struct cryptop *);
/* utility functions */
void sr_shutdown(void *);
@@ -817,6 +829,13 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
goto unwind;
strlcpy(sd->sd_name, "RAID 1", sizeof(sd->sd_name));
break;
+ case 'c':
+ if (no_chunk != 1) {
+ printf("too many c chunks\n");
+ goto unwind;
+ }
+ strlcpy(sd->sd_name, "RAID C", sizeof(sd->sd_name));
+ break;
default:
goto unwind;
}
@@ -887,17 +906,37 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
/* setup discipline pointers */
sd->sd_alloc_resources = sr_raid1_alloc_resources;
sd->sd_free_resources = sr_raid1_free_resources;
- sd->sd_scsi_inquiry = sr_raid1_inquiry;
- sd->sd_scsi_read_cap = sr_raid1_read_cap;
- sd->sd_scsi_tur = sr_raid1_tur;
- sd->sd_scsi_req_sense = sr_raid1_request_sense;
- sd->sd_scsi_start_stop = sr_raid1_start_stop;
- sd->sd_scsi_sync = sr_raid1_sync;
+ sd->sd_scsi_inquiry = sr_raid_inquiry;
+ sd->sd_scsi_read_cap = sr_raid_read_cap;
+ sd->sd_scsi_tur = sr_raid_tur;
+ sd->sd_scsi_req_sense = sr_raid_request_sense;
+ sd->sd_scsi_start_stop = sr_raid_start_stop;
+ sd->sd_scsi_sync = sr_raid_sync;
sd->sd_scsi_rw = sr_raid1_rw;
- sd->sd_set_chunk_state = sr_raid1_set_chunk_state;
- sd->sd_set_vol_state = sr_raid1_set_vol_state;
+ sd->sd_set_chunk_state = sr_raid_set_chunk_state;
+ sd->sd_set_vol_state = sr_raid_set_vol_state;
+ break;
+ case 'c':
+ /* fill out discipline members */
+ sd->sd_type = SR_MD_RAIDC;
+ sd->sd_max_ccb_per_wu = no_chunk;
+ sd->sd_max_wu = SR_RAIDC_NOWU;
+
+ /* setup discipline pointers */
+ sd->sd_alloc_resources = sr_raidc_alloc_resources;
+ sd->sd_free_resources = sr_raidc_free_resources;
+ sd->sd_scsi_inquiry = sr_raid_inquiry;
+ sd->sd_scsi_read_cap = sr_raid_read_cap;
+ sd->sd_scsi_tur = sr_raid_tur;
+ sd->sd_scsi_req_sense = sr_raid_request_sense;
+ sd->sd_scsi_start_stop = sr_raid_start_stop;
+ sd->sd_scsi_sync = sr_raid_sync;
+ sd->sd_scsi_rw = sr_raidc_rw;
+ sd->sd_set_chunk_state = sr_raid_set_chunk_state;
+ sd->sd_set_vol_state = sr_raid_set_vol_state;
break;
default:
+ printf("default %d\n", bc->bc_level);
goto unwind;
}
@@ -1355,13 +1394,13 @@ sr_raid1_free_resources(struct sr_discipline *sd)
}
int
-sr_raid1_inquiry(struct sr_workunit *wu)
+sr_raid_inquiry(struct sr_workunit *wu)
{
struct sr_discipline *sd = wu->swu_dis;
struct scsi_xfer *xs = wu->swu_xs;
struct scsi_inquiry_data inq;
- DNPRINTF(SR_D_DIS, "%s: sr_raid1_inquiry\n", DEVNAME(sd->sd_sc));
+ DNPRINTF(SR_D_DIS, "%s: sr_raid_inquiry\n", DEVNAME(sd->sd_sc));
bzero(&inq, sizeof(inq));
inq.device = T_DIRECT;
@@ -1381,13 +1420,13 @@ sr_raid1_inquiry(struct sr_workunit *wu)
}
int
-sr_raid1_read_cap(struct sr_workunit *wu)
+sr_raid_read_cap(struct sr_workunit *wu)
{
struct sr_discipline *sd = wu->swu_dis;
struct scsi_xfer *xs = wu->swu_xs;
struct scsi_read_cap_data rcd;
- DNPRINTF(SR_D_DIS, "%s: sr_raid1_read_cap\n", DEVNAME(sd->sd_sc));
+ DNPRINTF(SR_D_DIS, "%s: sr_raid_read_cap\n", DEVNAME(sd->sd_sc));
bzero(&rcd, sizeof(rcd));
_lto4b(sd->sd_vol.sv_meta.svm_size, rcd.addr);
@@ -1398,11 +1437,11 @@ sr_raid1_read_cap(struct sr_workunit *wu)
}
int
-sr_raid1_tur(struct sr_workunit *wu)
+sr_raid_tur(struct sr_workunit *wu)
{
struct sr_discipline *sd = wu->swu_dis;
- DNPRINTF(SR_D_DIS, "%s: sr_raid1_tur\n", DEVNAME(sd->sd_sc));
+ DNPRINTF(SR_D_DIS, "%s: sr_raid_tur\n", DEVNAME(sd->sd_sc));
if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
@@ -1428,12 +1467,12 @@ sr_raid1_tur(struct sr_workunit *wu)
}
int
-sr_raid1_request_sense(struct sr_workunit *wu)
+sr_raid_request_sense(struct sr_workunit *wu)
{
struct sr_discipline *sd = wu->swu_dis;
struct scsi_xfer *xs = wu->swu_xs;
- DNPRINTF(SR_D_DIS, "%s: sr_raid1_request_sense\n",
+ DNPRINTF(SR_D_DIS, "%s: sr_raid_request_sense\n",
DEVNAME(sd->sd_sc));
/* use latest sense data */
@@ -1452,14 +1491,14 @@ sr_raid1_request_sense(struct sr_workunit *wu)
}
int
-sr_raid1_start_stop(struct sr_workunit *wu)
+sr_raid_start_stop(struct sr_workunit *wu)
{
struct sr_discipline *sd = wu->swu_dis;
struct scsi_xfer *xs = wu->swu_xs;
struct scsi_start_stop *ss = (struct scsi_start_stop *)xs->cmd;
int rv = 1;
- DNPRINTF(SR_D_DIS, "%s: sr_raid1_start_stop\n",
+ DNPRINTF(SR_D_DIS, "%s: sr_raid_start_stop\n",
DEVNAME(sd->sd_sc));
if (!ss)
@@ -1486,19 +1525,19 @@ sr_raid1_start_stop(struct sr_workunit *wu)
}
int
-sr_raid1_sync(struct sr_workunit *wu)
+sr_raid_sync(struct sr_workunit *wu)
{
struct sr_discipline *sd = wu->swu_dis;
int s, rv = 0;
- DNPRINTF(SR_D_DIS, "%s: sr_raid1_sync\n", DEVNAME(sd->sd_sc));
+ DNPRINTF(SR_D_DIS, "%s: sr_raid_sync\n", DEVNAME(sd->sd_sc));
s = splbio();
sd->sd_sync = 1;
while (sd->sd_wu_pending > 1)
if (tsleep(sd, PRIBIO, "sr_sync", 60 * hz) == EWOULDBLOCK) {
- DNPRINTF(SR_D_DIS, "%s: sr_raid1_sync timeout\n",
+ DNPRINTF(SR_D_DIS, "%s: sr_raid_sync timeout\n",
DEVNAME(sd->sd_sc));
rv = 1;
break;
@@ -1689,7 +1728,7 @@ ragain:
/* XXX deal with polling */
- sr_raid1_startwu(wu);
+ sr_raid_startwu(wu);
queued:
splx(s);
@@ -1700,7 +1739,7 @@ bad:
}
void
-sr_raid1_startwu(struct sr_workunit *wu)
+sr_raid_startwu(struct sr_workunit *wu)
{
struct sr_discipline *sd = wu->swu_dis;
struct sr_ccb *ccb;
@@ -1775,7 +1814,7 @@ sr_raid1_intr(struct buf *bp)
SR_WU_INPROGRESS;
TAILQ_REMOVE(&sd->sd_wu_defq,
wu->swu_collider, swu_link);
- sr_raid1_startwu(wu->swu_collider);
+ sr_raid_startwu(wu->swu_collider);
}
break;
}
@@ -1797,11 +1836,11 @@ sr_raid1_intr(struct buf *bp)
}
void
-sr_raid1_set_chunk_state(struct sr_discipline *sd, int c, int new_state)
+sr_raid_set_chunk_state(struct sr_discipline *sd, int c, int new_state)
{
int old_state, s;
- DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid1_set_chunk_state %d -> %d\n",
+ DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_set_chunk_state %d -> %d\n",
DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
sd->sd_vol.sv_chunks[c]->src_meta.scm_devname, c, new_state);
@@ -1872,13 +1911,13 @@ done:
}
void
-sr_raid1_set_vol_state(struct sr_discipline *sd)
+sr_raid_set_vol_state(struct sr_discipline *sd)
{
int states[SR_MAX_STATES];
int new_state, i, s, nd;
int old_state = sd->sd_vol.sv_meta.svm_status;
- DNPRINTF(SR_D_STATE, "%s: %s: sr_raid1_set_vol_state\n",
+ DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n",
DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
nd = sd->sd_vol.sv_meta.svm_no_chunk;
@@ -1914,7 +1953,7 @@ sr_raid1_set_vol_state(struct sr_discipline *sd)
panic("invalid new_state");
}
- DNPRINTF(SR_D_STATE, "%s: %s: sr_raid1_set_vol_state %d -> %d\n",
+ DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state %d -> %d\n",
DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
old_state, new_state);
@@ -2727,3 +2766,376 @@ sr_print_metadata(struct sr_metadata *sm)
}
}
#endif /* SR_DEBUG */
+
+/* RAID crypto functions */
+struct cryptop *
+sr_raidc_getcryptop(struct sr_workunit *wu, int encrypt)
+{
+ struct scsi_xfer *xs = wu->swu_xs;
+ struct sr_discipline *sd = wu->swu_dis;
+ struct cryptop *crp;
+ struct cryptodesc *crd;
+ struct uio *uio;
+ int flags, i, n;
+ int blk = 0;
+
+ uio = malloc(sizeof(*uio), M_DEVBUF, M_WAITOK);
+ memset(uio, 0, sizeof(*uio));
+ uio->uio_iov = malloc(sizeof(*uio->uio_iov), M_DEVBUF, M_WAITOK);
+ uio->uio_iovcnt = 1;
+ uio->uio_iov->iov_base = xs->data;
+ uio->uio_iov->iov_len = xs->datalen;
+
+ if (xs->cmdlen == 10)
+ blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
+ else if (xs->cmdlen == 6)
+ blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
+
+ n = xs->datalen / 512;
+ flags = (encrypt ? CRD_F_ENCRYPT : 0) |
+ CRD_F_IV_PRESENT | CRD_F_IV_EXPLICIT;
+
+ crp = crypto_getreq(n);
+
+ crp->crp_sid = sd->mds.mdd_raidc.src_sid;
+ crp->crp_ilen = xs->datalen;
+ crp->crp_alloctype = M_DEVBUF;
+ crp->crp_buf = uio;
+ for (i = 0, crd = crp->crp_desc; crd; i++, crd = crd->crd_next) {
+ crd->crd_skip = 512 * i;
+ crd->crd_len = 512;
+ crd->crd_inject = 0;
+ crd->crd_flags = flags;
+ crd->crd_alg = CRYPTO_AES_CBC;
+ crd->crd_klen = 256;
+ crd->crd_rnd = 14;
+ crd->crd_key = sd->mds.mdd_raidc.src_key;
+ memset(crd->crd_iv, blk + i, sizeof(crd->crd_iv));
+ }
+ return crp;
+}
+
+void *
+sr_raidc_putcryptop(struct cryptop *crp)
+{
+ struct uio *uio = crp->crp_buf;
+ void *opaque = crp->crp_opaque;
+ free(uio->uio_iov, M_DEVBUF);
+ free(uio, M_DEVBUF);
+ crypto_freereq(crp);
+
+ return opaque;
+}
+
+int
+sr_raidc_alloc_resources(struct sr_discipline *sd)
+{
+ int rv = EINVAL;
+ struct cryptoini cri;
+
+ if (!sd)
+ return (rv);
+
+ DNPRINTF(SR_D_DIS, "%s: sr_raidc_alloc_resources\n",
+ DEVNAME(sd->sd_sc));
+
+ sr_alloc_wu(sd);
+ sr_alloc_ccb(sd);
+ memset(sd->mds.mdd_raidc.src_key, 'k', sizeof sd->mds.mdd_raidc.src_key);
+ bzero(&cri, sizeof(cri));
+ cri.cri_alg = CRYPTO_AES_CBC;
+ cri.cri_klen = 256;
+ cri.cri_rnd = 14;
+ cri.cri_key = sd->mds.mdd_raidc.src_key;
+ rv = crypto_newsession(&sd->mds.mdd_raidc.src_sid, &cri, 0);
+
+ return (rv);
+}
+
+int
+sr_raidc_free_resources(struct sr_discipline *sd)
+{
+ int rv = EINVAL;
+
+ if (!sd)
+ return (rv);
+
+ DNPRINTF(SR_D_DIS, "%s: sr_raidc_free_resources\n",
+ DEVNAME(sd->sd_sc));
+
+ sr_free_wu(sd);
+ sr_free_ccb(sd);
+
+ if (sd->sd_meta)
+ free(sd->sd_meta, M_DEVBUF);
+
+ rv = 0;
+ return (rv);
+}
+
+int
+sr_raidc_rw(struct sr_workunit *wu)
+{
+ struct cryptop *crp;
+
+ crp = sr_raidc_getcryptop(wu, 1);
+ crp->crp_callback = sr_raidc_rw2;
+ crp->crp_opaque = wu;
+ crypto_dispatch(crp);
+ return 0;
+}
+
+int
+sr_raidc_rw2(struct cryptop *crp)
+{
+ struct sr_workunit *wu = sr_raidc_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;
+ daddr64_t blk;
+
+
+ DNPRINTF(SR_D_DIS, "%s: sr_raidc_rw 0x%02x\n", DEVNAME(sd->sd_sc),
+ xs->cmd->opcode);
+
+ if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
+ DNPRINTF(SR_D_DIS, "%s: sr_raidc_rw device offline\n",
+ DEVNAME(sd->sd_sc));
+ goto bad;
+ }
+
+ if (xs->datalen == 0) {
+ printf("%s: %s: illegal block count\n",
+ DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
+ goto bad;
+ }
+
+ if (xs->cmdlen == 10)
+ blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
+ else if (xs->cmdlen == 6)
+ blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
+ else {
+ printf("%s: %s: illegal cmdlen\n", DEVNAME(sd->sd_sc),
+ sd->sd_vol.sv_meta.svm_devname);
+ goto bad;
+ }
+
+ blk += SR_META_SIZE + SR_META_OFFSET;
+
+ wu->swu_blk_start = blk;
+ wu->swu_blk_end = blk + xs->datalen - 1;
+ wu->swu_io_count = 1;
+
+ ccb = sr_get_ccb(sd);
+ if (!ccb) {
+ /* should never happen but handle more gracefully */
+ printf("%s: %s: too many ccbs queued\n",
+ DEVNAME(sd->sd_sc),
+ sd->sd_vol.sv_meta.svm_devname);
+ goto bad;
+ }
+
+ if (xs->flags & SCSI_POLL) {
+ panic("p");
+ 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_raidc_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;
+ }
+ } 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;
+ }
+
+ }
+ ccb->ccb_target = 0;
+ ccb->ccb_buf.b_dev = sd->sd_vol.sv_chunks[0]->src_dev_mm;
+ ccb->ccb_buf.b_vp = NULL;
+
+ LIST_INIT(&ccb->ccb_buf.b_dep);
+
+ TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link);
+
+ DNPRINTF(SR_D_DIS, "%s: %s: sr_raidc: 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,
+ ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
+
+
+ /* walk queue backwards and fill in collider if we have one */
+ s = splbio();
+ TAILQ_FOREACH_REVERSE(wup, &sd->sd_wu_pendq, sr_wu_list, swu_link) {
+ if (wu->swu_blk_end < wup->swu_blk_start ||
+ wup->swu_blk_end < wu->swu_blk_start)
+ continue;
+
+ /* we have an LBA collision, defer wu */
+ wu->swu_state = SR_WU_DEFERRED;
+ if (wup->swu_collider)
+ /* wu is on deferred queue, append to last wu */
+ while (wup->swu_collider)
+ wup = wup->swu_collider;
+
+ wup->swu_collider = wu;
+ TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu, swu_link);
+ sd->sd_wu_collisions++;
+ goto queued;
+ }
+
+ /* XXX deal with polling */
+
+ sr_raid_startwu(wu);
+
+queued:
+ splx(s);
+ return (0);
+bad:
+ /* wu is unwound by sr_put_wu */
+ return (1);
+}
+
+void
+sr_raidc_intr(struct buf *bp)
+{
+ struct sr_ccb *ccb = (struct sr_ccb *)bp;
+ struct sr_workunit *wu = ccb->ccb_wu;
+ struct cryptop *crp;
+
+ DNPRINTF(SR_D_INTR, "%s: sr_intr bp %x xs %x\n",
+ DEVNAME(sc), bp, xs);
+
+ DNPRINTF(SR_D_INTR, "%s: sr_intr: b_bcount: %d b_resid: %d"
+ " b_flags: 0x%0x\n", DEVNAME(sc), ccb->ccb_buf.b_bcount,
+ ccb->ccb_buf.b_resid, ccb->ccb_buf.b_flags);
+
+ crp = sr_raidc_getcryptop(wu, 0);
+ crp->crp_callback = sr_raidc_intr2;
+ crp->crp_opaque = bp;
+ crypto_dispatch(crp);
+}
+
+int
+sr_raidc_intr2(struct cryptop *crp)
+{
+ struct buf *bp = sr_raidc_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;
+
+ s = splbio();
+
+ if (ccb->ccb_buf.b_flags & B_ERROR) {
+ printf("%s: i/o error on block %llu\n", DEVNAME(sc),
+ ccb->ccb_buf.b_blkno);
+ wu->swu_ios_failed++;
+ ccb->ccb_state = SR_CCB_FAILED;
+ if (ccb->ccb_target != -1)
+ sd->sd_set_chunk_state(sd, ccb->ccb_target,
+ BIOC_SDOFFLINE);
+ else
+ panic("%s: invalid target on wu: %p", DEVNAME(sc), wu);
+ } else {
+ ccb->ccb_state = SR_CCB_OK;
+ wu->swu_ios_succeeded++;
+ }
+ wu->swu_ios_complete++;
+
+ DNPRINTF(SR_D_INTR, "%s: sr_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) {
+ if (wu->swu_ios_failed == wu->swu_ios_complete)
+ xs->error = XS_DRIVER_STUFFUP;
+ 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) {
+ /* wu on pendq, remove */
+ TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
+ pend = 1;
+
+ if (wu->swu_collider) {
+ /* restart deferred wu */
+ wu->swu_collider->swu_state =
+ SR_WU_INPROGRESS;
+ TAILQ_REMOVE(&sd->sd_wu_defq,
+ wu->swu_collider, swu_link);
+ sr_raid_startwu(wu->swu_collider);
+ }
+ break;
+ }
+ }
+
+ if (!pend)
+ 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);
+ }
+
+ splx(s);
+ return 0;
+}