As I've pointed out before, on panic we can be running on any CPU and our disk controller's interrupts can interrupt on the other one. Since we'll most likely be holding a kernel lock, dealing with unlocking it might get hairy very fast. Instead what we could do to improve the chances of a clean shutdown on panic is to instruct our disk subsystem to do polled I/O that will be run on the same CPU with the panic.
Initially I wanted to move "cold = 1" earlier in boot(), but after talking to Miod, it started to look like a bad idea. Thoughts? diff --git sys/dev/ata/ata_wdc.c sys/dev/ata/ata_wdc.c index 1f52488..aea9ec1 100644 --- sys/dev/ata/ata_wdc.c +++ sys/dev/ata/ata_wdc.c @@ -199,20 +199,22 @@ wd_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size, int op, voi */ int wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio) { struct wdc_xfer *xfer; struct channel_softc *chp = drvp->chnl_softc; xfer = wdc_get_xfer(WDC_NOSLEEP); if (xfer == NULL) return WDC_TRY_AGAIN; + if (panicstr) + ata_bio->flags |= ATA_POLL; if (ata_bio->flags & ATA_POLL) xfer->c_flags |= C_POLL; if (!(ata_bio->flags & ATA_POLL) && (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) && (ata_bio->flags & ATA_SINGLE) == 0 && (ata_bio->bcount > 512 || (chp->wdc->quirks & WDC_QUIRK_NOSHORTDMA) == 0)) xfer->c_flags |= C_DMA; xfer->drive = drvp->drive; xfer->cmd = ata_bio; diff --git sys/scsi/scsi_base.c sys/scsi/scsi_base.c index 9cf6b45..3afcc29 100644 --- sys/scsi/scsi_base.c +++ sys/scsi/scsi_base.c @@ -1267,20 +1267,22 @@ scsi_report_luns(struct scsi_link *sc_link, int selectreport, return (error); } void scsi_xs_exec(struct scsi_xfer *xs) { xs->error = XS_NOERROR; xs->resid = xs->datalen; xs->status = 0; CLR(xs->flags, ITSDONE); + if (panicstr) + SET(xs->flags, SCSI_AUTOCONF); #ifdef SCSIDEBUG if (xs->sc_link->flags & SDEV_DB1) { scsi_xs_show(xs); if (xs->datalen && (xs->flags & SCSI_DATA_OUT)) scsi_show_mem(xs->data, min(64, xs->datalen)); } #endif /* The adapter's scsi_cmd() is responsible for calling scsi_done(). */