diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2014-04-22 08:48:52 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2014-04-22 08:48:52 +0000 |
commit | 28c44638912d392c7db911f18fa2cf4e50729626 (patch) | |
tree | 56ddbf616ab4ddd927b808b711beabbe173ce5bd /sys | |
parent | ad7156d35e09c6c4acaad6f32dba7f4573078765 (diff) |
move vscsi from using scsi_req_probe and scsi_req_detach to using
the newly minted scsi_probe and scsi_detach respectively from a
task it runs itself.
the probe and detach ioctls requests work the same before and after
this change, but this paves the way for vscsi being able to report
the status of these requests back to userland.
discussed with claudio@
tested with current iscsid and an md3200i
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/vscsi.c | 76 |
1 files changed, 68 insertions, 8 deletions
diff --git a/sys/dev/vscsi.c b/sys/dev/vscsi.c index 16250ea1158..13497a2b272 100644 --- a/sys/dev/vscsi.c +++ b/sys/dev/vscsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vscsi.c,v 1.28 2014/01/22 01:21:33 dlg Exp $ */ +/* $OpenBSD: vscsi.c,v 1.29 2014/04/22 08:48:51 dlg Exp $ */ /* * Copyright (c) 2008 David Gwynne <dlg@openbsd.org> @@ -27,6 +27,7 @@ #include <sys/queue.h> #include <sys/rwlock.h> #include <sys/pool.h> +#include <sys/task.h> #include <sys/ioctl.h> #include <sys/poll.h> #include <sys/selinfo.h> @@ -106,7 +107,9 @@ struct scsi_adapter vscsi_switch = { int vscsi_i2t(struct vscsi_softc *, struct vscsi_ioc_i2t *); int vscsi_data(struct vscsi_softc *, struct vscsi_ioc_data *, int); int vscsi_t2i(struct vscsi_softc *, struct vscsi_ioc_t2i *); - +int vscsi_devevent(struct vscsi_softc *, u_long, + struct vscsi_ioc_devevent *); +void vscsi_devevent_task(void *, void *); void vscsi_done(struct vscsi_softc *, struct vscsi_ccb *); void * vscsi_ccb_get(void *); @@ -292,7 +295,6 @@ int vscsiioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) { struct vscsi_softc *sc = DEV2SC(dev); - struct vscsi_ioc_devevent *de = (struct vscsi_ioc_devevent *)addr; int read = 0; int err = 0; @@ -317,12 +319,9 @@ vscsiioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; case VSCSI_REQPROBE: - err = scsi_req_probe(sc->sc_scsibus, de->target, de->lun); - break; - case VSCSI_REQDETACH: - err = scsi_req_detach(sc->sc_scsibus, de->target, de->lun, - DETACH_FORCE); + err = vscsi_devevent(sc, cmd, + (struct vscsi_ioc_devevent *)addr); break; default: @@ -473,6 +472,67 @@ vscsi_t2i(struct vscsi_softc *sc, struct vscsi_ioc_t2i *t2i) return (rv); } +struct vscsi_devevent_task { + struct task t; + struct vscsi_ioc_devevent de; + u_long cmd; +}; + +int +vscsi_devevent(struct vscsi_softc *sc, u_long cmd, + struct vscsi_ioc_devevent *de) +{ + struct vscsi_devevent_task *dt; + + dt = malloc(sizeof(*dt), M_TEMP, M_WAITOK | M_CANFAIL); + if (dt == NULL) + return (ENOMEM); + + task_set(&dt->t, vscsi_devevent_task, sc, dt); + dt->de = *de; + dt->cmd = cmd; + + device_ref(&sc->sc_dev); + task_add(systq, &dt->t); + + return (0); +} + +void +vscsi_devevent_task(void *xsc, void *xdt) +{ + struct vscsi_softc *sc = xsc; + struct vscsi_devevent_task *dt = xdt; + int state; + + mtx_enter(&sc->sc_state_mtx); + state = sc->sc_state; + mtx_leave(&sc->sc_state_mtx); + + if (state != VSCSI_S_RUNNING) + goto gone; + + switch (dt->cmd) { + case VSCSI_REQPROBE: + scsi_probe(sc->sc_scsibus, dt->de.target, dt->de.lun); + break; + case VSCSI_REQDETACH: + scsi_detach(sc->sc_scsibus, dt->de.target, dt->de.lun, + DETACH_FORCE); + break; +#ifdef DIAGNOSTIC + default: + panic("unexpected vscsi_devevent cmd"); + /* NOTREACHED */ + } +#endif + +gone: + device_unref(&sc->sc_dev); + + free(dt, M_TEMP); +} + int vscsipoll(dev_t dev, int events, struct proc *p) { |