Index: sys/cam/ata/ata_da.c =================================================================== --- sys/cam/ata/ata_da.c +++ sys/cam/ata/ata_da.c @@ -1081,6 +1081,8 @@ (u_int8_t *) virtual, length, ada_default_timeout*1000); + ataio.ccb_h.xflags |= CAM_CCB_DUMP; + if ((softc->flags & ADA_FLAG_CAN_48BIT) && (lba + count >= ATA_MAX_28BIT_LBA || count >= 256)) { @@ -1113,8 +1115,9 @@ CAM_DIR_NONE, 0, NULL, - 0, + 1, 5*1000); + ataio.ccb_h.xflags |= CAM_CCB_DUMP; if (softc->flags & ADA_FLAG_CAN_48BIT) ata_48bit_cmd(&ataio, ATA_FLUSHCACHE48, 0, 0, 0); Index: sys/cam/cam_ccb.h =================================================================== --- sys/cam/cam_ccb.h +++ sys/cam/cam_ccb.h @@ -116,7 +116,8 @@ typedef enum { CAM_USER_DATA_ADDR = 0x00000002,/* Userspace data pointers */ CAM_SG_FORMAT_IOVEC = 0x00000004,/* iovec instead of busdma S/G*/ - CAM_UNMAPPED_BUF = 0x00000008 /* use unmapped I/O */ + CAM_UNMAPPED_BUF = 0x00000008,/* use unmapped I/O */ + CAM_CCB_DUMP = 0x00000010,/* polled ccb used during dump */ } ccb_xflags; /* XPT Opcodes for xpt_action */ Index: sys/cam/cam_xpt.c =================================================================== --- sys/cam/cam_xpt.c +++ sys/cam/cam_xpt.c @@ -190,6 +190,7 @@ static struct cam_doneq cam_doneqs[MAXCPU]; static int cam_num_doneqs; static struct proc *cam_proc; +static STAILQ_HEAD(, ccb_hdr) cam_nondump_ccbs; SYSCTL_INT(_kern_cam, OID_AUTO, num_doneqs, CTLFLAG_RDTUN, &cam_num_doneqs, 0, "Number of completion queues/threads"); @@ -5480,6 +5481,21 @@ } } + /* + * Avoid completing non-dump I/O when we're dumping core after a panic. + * Otherwise we may call into filesystem or pager code, potentially + * resulting in a deadlock. Note that this doesn't affect dumps that + * were started manually since we aim to keep the system usable after it + * has been resumed. + */ + if (__predict_false(dumping && SCHEDULER_STOPPED() && + ((ccb_h->xflags & CAM_CCB_DUMP) == 0))) { + STAILQ_INSERT_TAIL(&cam_nondump_ccbs, ccb_h, sim_links.stqe); + if ((ccb_h->status & CAM_DEV_QFRZN) != 0) + (void)cam_release_devq(ccb_h->path, 0, 0, 0, FALSE); + return; + } + if ((ccb_h->flags & CAM_UNLOCKED) == 0) { if (mtx == NULL) { mtx = xpt_path_mtx(ccb_h->path); Index: sys/cam/nvme/nvme_da.c =================================================================== --- sys/cam/nvme/nvme_da.c +++ sys/cam/nvme/nvme_da.c @@ -426,6 +426,7 @@ xpt_setup_ccb(&nvmeio.ccb_h, periph->path, CAM_PRIORITY_NORMAL); nvmeio.ccb_state = NDA_CCB_DUMP; nda_nvme_write(softc, &nvmeio, virtual, lba, length, count); + nvmeio.ccb_h.xflags |= CAM_CCB_DUMP; error = cam_periph_runccb((union ccb *)&nvmeio, cam_periph_error, 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); if (error != 0) @@ -439,6 +440,7 @@ nvmeio.ccb_state = NDA_CCB_DUMP; nda_nvme_flush(softc, &nvmeio); + nvmeio.ccb_h.xflags |= CAM_CCB_DUMP; error = cam_periph_runccb((union ccb *)&nvmeio, cam_periph_error, 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); if (error != 0) Index: sys/cam/scsi/scsi_da.c =================================================================== --- sys/cam/scsi/scsi_da.c +++ sys/cam/scsi/scsi_da.c @@ -1847,6 +1847,8 @@ /*dxfer_len*/length, /*sense_len*/SSD_FULL_SIZE, da_default_timeout * 1000); + csio.ccb_h.xflags |= CAM_CCB_DUMP; + error = cam_periph_runccb((union ccb *)&csio, cam_periph_error, 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); if (error != 0) @@ -1858,7 +1860,6 @@ * Sync the disk cache contents to the physical media. */ if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { - xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL); csio.ccb_h.ccb_state = DA_CCB_DUMP; scsi_synchronize_cache(&csio, @@ -1869,6 +1870,8 @@ /*lb_count*/0, SSD_FULL_SIZE, 5 * 1000); + csio.ccb_h.xflags |= CAM_CCB_DUMP; + error = cam_periph_runccb((union ccb *)&csio, cam_periph_error, 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); if (error != 0)