> Date: Thu, 7 May 2015 20:58:53 +0200 > From: Mike Belopuhov <m...@belopuhov.com> > > 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?
I'm not necessarily against forcing polled I/O in this case, but it sucks a bit that we have to add checks in fairly low-level code to accomplish this. And I'm not sure if disk I/O is the only thing that we should worry about here. I think tsleep(9) and msleep(9) need to release and re-acquire the kernel lock in the "cold || panicstr" case. We might need this for handling interrupts during autoconf as soon as we start distributing interrupts over CPUs. > 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(). */ > >