diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2010-11-06 23:01:57 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2010-11-06 23:01:57 +0000 |
commit | 0cd04aa2ccdc2ce4b05e2402a6819a84c8ee9f7e (patch) | |
tree | fb0086bae804687e8e76c89f4677f89bb9292abb /sys | |
parent | d61cd1c11441e91ef0218dc60903909298a927f0 (diff) |
Move raid1 and crypto io to a workq. This is to avoid a potential VOP_
call while in interrupt context.
Contains an additional spl dance as found by thib.
Tested by many opn various arches. Note that raid 0/4/5/6 have not been
moved over yet.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/softraid.c | 42 | ||||
-rw-r--r-- | sys/dev/softraid_crypto.c | 59 | ||||
-rw-r--r-- | sys/dev/softraid_raid1.c | 9 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 9 |
4 files changed, 78 insertions, 41 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index 16c78026a85..cecb4e8cc35 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.215 2010/10/12 00:53:32 krw Exp $ */ +/* $OpenBSD: softraid.c,v 1.216 2010/11/06 23:01:56 marco Exp $ */ /* * Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org> @@ -126,6 +126,7 @@ void sr_rebuild(void *); void sr_rebuild_thread(void *); void sr_roam_chunks(struct sr_discipline *); int sr_chunk_in_use(struct sr_softc *, dev_t); +void sr_startwu_callback(void *, void *); /* don't include these on RAMDISK */ #ifndef SMALL_KERNEL @@ -1806,6 +1807,8 @@ sr_wu_put(struct sr_workunit *wu) wu->swu_fake = 0; wu->swu_flags = 0; + if (wu->swu_cb_active == 1) + panic("%s: sr_wu_put", DEVNAME(sd->sd_sc)); while ((ccb = TAILQ_FIRST(&wu->swu_ccb)) != NULL) { TAILQ_REMOVE(&wu->swu_ccb, ccb, ccb_link); sr_ccb_put(ccb); @@ -2563,6 +2566,9 @@ sr_hotspare_rebuild(struct sr_discipline *sd) busy = 0; s = splbio(); + if (wu->swu_cb_active == 1) + panic("%s: sr_hotspare_rebuild", + DEVNAME(sd->sd_sc)); TAILQ_FOREACH(wu, &sd->sd_wu_pendq, swu_link) { TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) { if (ccb->ccb_target == chunk_no) @@ -2816,6 +2822,11 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK | M_ZERO); sd->sd_sc = sc; SLIST_INIT(&sd->sd_meta_opt); + sd->sd_workq = workq_create("srdis", 1, IPL_BIO); + if (sd->sd_workq == NULL) { + printf("%s: could not create workq\n", DEVNAME(sc)); + goto unwind; + } if (sr_discipline_init(sd, bc->bc_level)) { printf("%s: could not initialize discipline\n", DEVNAME(sc)); goto unwind; @@ -3407,6 +3418,9 @@ sr_discipline_shutdown(struct sr_discipline *sd) sr_chunks_unwind(sc, &sd->sd_vol.sv_chunk_list); + if (sd->sd_workq) + workq_destroy(sd->sd_workq); + if (sd) sr_discipline_free(sd); @@ -3625,10 +3639,29 @@ sr_raid_sync(struct sr_workunit *wu) } void +sr_startwu_callback(void *arg1, void *arg2) +{ + struct sr_discipline *sd = arg1; + struct sr_workunit *wu = arg2; + struct sr_ccb *ccb; + int s; + + s = splbio(); + if (wu->swu_cb_active == 1) + panic("%s: sr_startwu_callback", DEVNAME(sd->sd_sc)); + wu->swu_cb_active = 1; + + TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) + VOP_STRATEGY(&ccb->ccb_buf); + + wu->swu_cb_active = 0; + splx(s); +} + +void sr_raid_startwu(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; - struct sr_ccb *ccb; splassert(IPL_BIO); @@ -3643,9 +3676,8 @@ sr_raid_startwu(struct sr_workunit *wu) TAILQ_INSERT_TAIL(&sd->sd_wu_pendq, wu, swu_link); /* start all individual ios */ - TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) { - VOP_STRATEGY(&ccb->ccb_buf); - } + workq_queue_task(sd->sd_workq, &wu->swu_wqt, 0, sr_startwu_callback, + sd, wu); } void diff --git a/sys/dev/softraid_crypto.c b/sys/dev/softraid_crypto.c index 9ebb3c74f1b..a7fb7a6a331 100644 --- a/sys/dev/softraid_crypto.c +++ b/sys/dev/softraid_crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid_crypto.c,v 1.57 2010/09/27 19:49:43 thib Exp $ */ +/* $OpenBSD: softraid_crypto.c,v 1.58 2010/11/06 23:01:56 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2008 Hans-Joerg Hoexer <hshoexer@openbsd.org> @@ -164,11 +164,11 @@ sr_crypto_create(struct sr_discipline *sd, struct bioc_createraid *bc, } else if (sr_crypto_get_kdf(bc, sd)) goto done; - + /* Passphrase volumes cannot be automatically assembled. */ if (!(bc->bc_flags & BIOC_SCNOAUTOASSEMBLE) && bc->bc_key_disk == NODEV) goto done; - + strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name)); sd->sd_meta->ssdi.ssd_size = coerced_size; @@ -194,15 +194,12 @@ sr_crypto_assemble(struct sr_discipline *sd, struct bioc_createraid *bc, goto done; if (bc->bc_key_disk != NODEV) { - /* Read the mask key from the key disk. */ sd->mds.mdd_crypto.key_disk = sr_crypto_read_key_disk(sd, bc->bc_key_disk); if (sd->mds.mdd_crypto.key_disk == NULL) goto done; - } else if (bc->bc_opaque_flags & BIOC_SOOUT) { - /* provide userland with kdf hint */ if (bc->bc_opaque == NULL) goto done; @@ -218,10 +215,8 @@ sr_crypto_assemble(struct sr_discipline *sd, struct bioc_createraid *bc, /* we're done */ bc->bc_opaque_status = BIOC_SOINOUT_OK; rv = EAGAIN; - goto done; - + goto done; } else if (bc->bc_opaque_flags & BIOC_SOIN) { - /* get kdf with maskkey from userland */ if (sr_crypto_get_kdf(bc, sd)) goto done; @@ -253,10 +248,11 @@ sr_crypto_getcryptop(struct sr_workunit *wu, int encrypt) s = splbio(); uio = pool_get(&sd->mds.mdd_crypto.sr_uiopl, PR_ZERO | PR_NOWAIT); if (uio == NULL) - goto unwind; - uio->uio_iov = pool_get(&sd->mds.mdd_crypto.sr_iovpl, PR_NOWAIT); + goto poolunwind; + uio->uio_iov = pool_get(&sd->mds.mdd_crypto.sr_iovpl, + PR_ZERO | PR_NOWAIT); if (uio->uio_iov == NULL) - goto unwind; + goto poolunwind; splx(s); uio->uio_iovcnt = 1; @@ -318,11 +314,14 @@ sr_crypto_getcryptop(struct sr_workunit *wu, int encrypt) } return (crp); +poolunwind: + splx(s); unwind: if (crp) crypto_freereq(crp); if (uio && uio->uio_iov) - if (wu->swu_xs->flags & SCSI_DATA_OUT) + if ((wu->swu_xs->flags & SCSI_DATA_OUT) && + uio->uio_iov->iov_base) free(uio->uio_iov->iov_base, M_DEVBUF); s = splbio(); @@ -346,7 +345,7 @@ sr_crypto_putcryptop(struct cryptop *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) + if ((wu->swu_xs->flags & SCSI_DATA_OUT) && uio->uio_iov->iov_base) free(uio->uio_iov->iov_base, M_DEVBUF); s = splbio(); pool_put(&sd->mds.mdd_crypto.sr_iovpl, uio->uio_iov); @@ -783,7 +782,7 @@ sr_crypto_create_key_disk(struct sr_discipline *sd, dev_t dev) DEVNAME(sc), devname); goto fail; } - + goto done; fail: @@ -867,13 +866,7 @@ sr_crypto_read_key_disk(struct sr_discipline *sd, dev_t dev) /* * Read and validate key disk metadata. */ - sm = malloc(SR_META_SIZE * 512, M_DEVBUF, M_NOWAIT|M_ZERO); - if (sm == NULL) { - printf("%s: not enough memory for metadata buffer\n", - DEVNAME(sc)); - goto done; - } - + sm = malloc(SR_META_SIZE * 512, M_DEVBUF, M_WAITOK | M_ZERO); if (sr_meta_native_read(sd, dev, sm, NULL)) { printf("%s: native bootprobe could not read native " "metadata\n", DEVNAME(sc)); @@ -882,7 +875,7 @@ sr_crypto_read_key_disk(struct sr_discipline *sd, dev_t dev) if (sr_meta_validate(sd, dev, sm, NULL)) { DNPRINTF(SR_D_META, "%s: invalid metadata\n", - DEVNAME(sc)); + DEVNAME(sc)); goto done; } @@ -893,13 +886,7 @@ sr_crypto_read_key_disk(struct sr_discipline *sd, dev_t dev) } /* Construct key disk chunk. */ - key_disk = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_NOWAIT|M_ZERO); - if (key_disk == NULL) { - printf("%s: not enough memory for chunk\n", - DEVNAME(sc)); - goto done; - } - + key_disk = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_WAITOK | M_ZERO); key_disk->src_dev_mm = dev; key_disk->src_vn = vn; key_disk->src_size = 0; @@ -1106,8 +1093,8 @@ sr_crypto_meta_opt_load(struct sr_discipline *sd, struct sr_meta_opt *om) sd->mds.mdd_crypto.scr_meta = &om->somi.som_meta.smm_crypto; rv = 0; } - - return rv; + + return (rv); } int @@ -1122,7 +1109,7 @@ sr_crypto_rw(struct sr_workunit *wu) if (wu->swu_xs->flags & SCSI_DATA_OUT) { crp = sr_crypto_getcryptop(wu, 1); if (crp == NULL) - panic("sr_crypto_getcryptop"); + panic("sr_crypto_rw: no crypto op"); crp->crp_callback = sr_crypto_write; crp->crp_opaque = wu; s = splvm(); @@ -1211,6 +1198,8 @@ sr_crypto_rw2(struct sr_workunit *wu, struct cryptop *crp) LIST_INIT(&ccb->ccb_buf.b_dep); + if (wu->swu_cb_active == 1) + panic("%s: sr_crypto_rw2", DEVNAME(sd->sd_sc)); TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link); DNPRINTF(SR_D_DIS, "%s: %s: sr_crypto_rw2: b_bcount: %d " @@ -1305,7 +1294,7 @@ sr_crypto_intr(struct buf *bp) if ((xs->flags & SCSI_DATA_IN) && (xs->error == XS_NOERROR)) { crp = sr_crypto_getcryptop(wu, 0); if (crp == NULL) - panic("sr_crypto_getcryptop"); + panic("sr_crypto_intr: no crypto op"); ccb->ccb_opaque = crp; crp->crp_callback = sr_crypto_read; crp->crp_opaque = wu; @@ -1341,6 +1330,8 @@ sr_crypto_finish_io(struct sr_workunit *wu) xs->resid = 0; + if (wu->swu_cb_active == 1) + panic("%s: sr_crypto_finish_io", DEVNAME(sd->sd_sc)); TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) { if (ccb->ccb_opaque == NULL) continue; diff --git a/sys/dev/softraid_raid1.c b/sys/dev/softraid_raid1.c index 49cc61a3f2b..2a44e996cc2 100644 --- a/sys/dev/softraid_raid1.c +++ b/sys/dev/softraid_raid1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid_raid1.c,v 1.25 2010/07/02 09:20:26 jsing Exp $ */ +/* $OpenBSD: softraid_raid1.c,v 1.26 2010/11/06 23:01:56 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * @@ -476,6 +476,8 @@ ragain: LIST_INIT(&b->b_dep); + if (wu->swu_cb_active == 1) + panic("%s: sr_raid1_rw", DEVNAME(sd->sd_sc)); TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link); DNPRINTF(SR_D_DIS, "%s: %s: sr_raid1: b_bcount: %d " @@ -560,6 +562,9 @@ sr_raid1_intr(struct buf *bp) printf("%s: retrying read on block %lld\n", DEVNAME(sc), b->b_blkno); sr_ccb_put(ccb); + if (wu->swu_cb_active == 1) + panic("%s: sr_raid1_intr_cb", + DEVNAME(sd->sd_sc)); TAILQ_INIT(&wu->swu_ccb); wu->swu_state = SR_WU_RESTART; if (sd->sd_scsi_rw(wu)) @@ -647,6 +652,8 @@ sr_raid1_recreate_wu(struct sr_workunit *wu) DNPRINTF(SR_D_INTR, "%s: sr_raid1_recreate_wu: %p\n", wup); /* toss all ccbs */ + if (wu->swu_cb_active == 1) + panic("%s: sr_raid1_recreate_wu", DEVNAME(sd->sd_sc)); while ((ccb = TAILQ_FIRST(&wup->swu_ccb)) != NULL) { TAILQ_REMOVE(&wup->swu_ccb, ccb, ccb_link); sr_ccb_put(ccb); diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h index f381d71fd3f..7d2abb06c64 100644 --- a/sys/dev/softraidvar.h +++ b/sys/dev/softraidvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraidvar.h,v 1.95 2010/08/30 17:32:40 jsing Exp $ */ +/* $OpenBSD: softraidvar.h,v 1.96 2010/11/06 23:01:56 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org> @@ -346,6 +346,11 @@ struct sr_workunit { /* all ios that make up this workunit */ struct sr_ccb_list swu_ccb; + /* task memory */ + struct workq_task swu_wqt; + struct workq_task swu_intr; + int swu_cb_active; /* in callback */ + TAILQ_ENTRY(sr_workunit) swu_link; }; @@ -485,6 +490,8 @@ struct sr_discipline { } sd_dis_specific;/* dis specific members */ #define mds sd_dis_specific + struct workq *sd_workq; + /* discipline metadata */ struct sr_metadata *sd_meta; /* in memory copy of metadata */ void *sd_meta_foreign; /* non native metadata */ |