diff options
-rw-r--r-- | sys/scsi/sd.c | 35 | ||||
-rw-r--r-- | sys/scsi/sdvar.h | 3 |
2 files changed, 36 insertions, 2 deletions
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index 275e17e93af..e7b8ed619f1 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sd.c,v 1.244 2012/10/15 16:29:07 deraadt Exp $ */ +/* $OpenBSD: sd.c,v 1.245 2012/12/19 19:52:11 kettenis Exp $ */ /* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ /*- @@ -87,6 +87,7 @@ int sddetach(struct device *, int); void sdminphys(struct buf *); int sdgetdisklabel(dev_t, struct sd_softc *, struct disklabel *, int); void sdstart(struct scsi_xfer *); +void sd_shutdown(void *); int sd_interpret_sense(struct scsi_xfer *); int sd_read_cap_10(struct sd_softc *, int); int sd_read_cap_16(struct sd_softc *, int); @@ -259,6 +260,19 @@ sdattach(struct device *parent, struct device *self, void *aux) sd_ioctl_cache(sc, DIOCSCACHE, &dkc); } + /* + * Establish a shutdown hook so that we can ensure that + * our data has actually made it onto the platter at + * shutdown time. Note that this relies on the fact + * that the shutdown hook code puts us at the head of + * the list (thus guaranteeing that our hook runs before + * our ancestors'). + */ + if ((sc->sc_sdhook = + shutdownhook_establish(sd_shutdown, sc)) == NULL) + printf("%s: WARNING: unable to establish shutdown hook\n", + sc->sc_dev.dv_xname); + /* Attach disk. */ disk_attach(&sc->sc_dev, &sc->sc_dk); } @@ -311,6 +325,10 @@ sddetach(struct device *self, int flags) disk_gone(sdopen, self->dv_unit); + /* Get rid of the shutdown hook. */ + if (sc->sc_sdhook != NULL) + shutdownhook_disestablish(sc->sc_sdhook); + /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); @@ -1109,6 +1127,21 @@ sdgetdisklabel(dev_t dev, struct sd_softc *sc, struct disklabel *lp, return readdisklabel(DISKLABELDEV(dev), sdstrategy, lp, spoofonly); } + +void +sd_shutdown(void *arg) +{ + struct sd_softc *sc = (struct sd_softc *)arg; + + /* + * If the disk cache needs to be flushed, and the disk supports + * it, flush it. We're cold at this point, so we poll for + * completion. + */ + if ((sc->flags & SDF_DIRTY) != 0) + sd_flush(sc, SCSI_AUTOCONF); +} + /* * Check Errors */ diff --git a/sys/scsi/sdvar.h b/sys/scsi/sdvar.h index 4e2accdfde1..220190965ad 100644 --- a/sys/scsi/sdvar.h +++ b/sys/scsi/sdvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sdvar.h,v 1.39 2012/10/08 21:47:51 deraadt Exp $ */ +/* $OpenBSD: sdvar.h,v 1.40 2012/12/19 19:52:11 kettenis Exp $ */ /* $NetBSD: sdvar.h,v 1.7 1998/08/17 00:49:03 mycroft Exp $ */ /*- @@ -69,6 +69,7 @@ struct sd_softc { u_int32_t unmap_sectors; /* maximum sectors/unmap */ u_int32_t unmap_descs; /* maximum descriptors/unmap */ } params; + void *sc_sdhook; /* our shutdown hook */ struct timeout sc_timeout; struct scsi_xshandler sc_xsh; |