diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-03-17 18:05:40 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-03-17 18:05:40 +0000 |
commit | 16951446ab99aa9b4a7285486810ca6158564d48 (patch) | |
tree | 2afd67224907283ff7dc486f2ae18a62f9fc8a05 /sys/scsi/sd.c | |
parent | 10d348fb0422aec8c3ed708d14327d2ab4b0cc2c (diff) |
Do not access the scsi link structure in sdclose() if the disk
device is already dying. Delete the sc_timeout when setting the
SDF_DYING flag as the timeout delete in sdclose() may not be reached.
OK krw@
Diffstat (limited to 'sys/scsi/sd.c')
-rw-r--r-- | sys/scsi/sd.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index 170a191b205..f9f002a5960 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sd.c,v 1.266 2016/03/16 15:01:55 bluhm Exp $ */ +/* $OpenBSD: sd.c,v 1.267 2016/03/17 18:05:39 bluhm Exp $ */ /* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ /*- @@ -305,6 +305,7 @@ sdactivate(struct device *self, int act) break; case DVACT_DEACTIVATE: sc->flags |= SDF_DYING; + timeout_del(&sc->sc_timeout); scsi_xsh_del(&sc->sc_xsh); break; } @@ -496,6 +497,7 @@ sdclose(dev_t dev, int flag, int fmt, struct proc *p) struct scsi_link *link; struct sd_softc *sc; int part = DISKPART(dev); + int error = 0; sc = sdlookup(DISKUNIT(dev)); if (sc == NULL) @@ -514,14 +516,26 @@ sdclose(dev_t dev, int flag, int fmt, struct proc *p) if ((sc->flags & SDF_DIRTY) != 0) sd_flush(sc, 0); + if (sc->flags & SDF_DYING) { + error = ENXIO; + goto die; + } if ((link->flags & SDEV_REMOVABLE) != 0) scsi_prevent(link, PR_ALLOW, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_SILENT); + if (sc->flags & SDF_DYING) { + error = ENXIO; + goto die; + } link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED); if (link->flags & SDEV_EJECTING) { scsi_start(link, SSS_STOP|SSS_LOEJ, 0); + if (sc->flags & SDF_DYING) { + error = ENXIO; + goto die; + } link->flags &= ~SDEV_EJECTING; } @@ -529,9 +543,10 @@ sdclose(dev_t dev, int flag, int fmt, struct proc *p) scsi_xsh_del(&sc->sc_xsh); } +die: disk_unlock(&sc->sc_dk); device_unref(&sc->sc_dev); - return 0; + return (error); } /* |