--- a/sys/bus/cam/scsi/scsi_sg.c +++ b/sys/bus/cam/scsi/scsi_sg.c @@ -787,8 +787,20 @@ } if (rdwr == NULL) { cam_periph_unlock(periph); - if (tsleep(&hstat, PCATCH, "sgnull", 0) == ERESTART) - return(EAGAIN); + /* + * DF-2283: the &hstat channel has NO wakeup source (it is a + * stack address unique to this invocation; sgdone only ever + * wakeup()s rdwr or &ccb_h.cbfcnp). Bound the sleep with + * the command timeout so an unmatched pack_id cannot block + * read(2) forever; a timeout means the queue can never + * satisfy this request. + */ + error = tsleep(&hstat, PCATCH, "sgnull", + sc->sg_timeout ? sc->sg_timeout : 60 * hz); + if (error == ERESTART) + return (EAGAIN); + if (error != 0) /* EWOULDBLOCK: timed out */ + return (ENOENT); cam_periph_lock(periph); goto search; }