Remove direct ata_completed() call options from ata_finish(), except for the
kernel dumping case. ata_completed() may initiate ata_reinit() on error, that may lead to drives attach or detach. Attach and detach are sending requests to drives and sleep waiting for results. But ata_finish() can be called directly from interrupt handler where sleeping is prohibited, so we must break this chain somewhere. This place seems to fit best.
This commit is contained in:
parent
a9d25ec695
commit
69328334a6
@ -627,7 +627,7 @@ ata_getparam(struct ata_device *atadev, int init)
|
||||
request->timeout = 1;
|
||||
request->retries = 0;
|
||||
request->u.ata.command = command;
|
||||
request->flags = (ATA_R_READ|ATA_R_AT_HEAD|ATA_R_DIRECT|ATA_R_QUIET);
|
||||
request->flags = (ATA_R_READ|ATA_R_AT_HEAD|ATA_R_THREAD|ATA_R_QUIET);
|
||||
request->data = (void *)&atadev->param;
|
||||
request->bytecount = sizeof(struct ata_params);
|
||||
request->donecount = 0;
|
||||
|
@ -367,7 +367,6 @@ struct ata_request {
|
||||
#define ATA_R_AT_HEAD 0x00000200
|
||||
#define ATA_R_REQUEUE 0x00000400
|
||||
#define ATA_R_THREAD 0x00000800
|
||||
#define ATA_R_DIRECT 0x00001000
|
||||
|
||||
#define ATA_R_DEBUG 0x10000000
|
||||
#define ATA_R_DANGER1 0x20000000
|
||||
|
@ -237,14 +237,8 @@ ata_start(device_t dev)
|
||||
void
|
||||
ata_finish(struct ata_request *request)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(request->parent);
|
||||
|
||||
/*
|
||||
* if in ATA_STALL_QUEUE state or request has ATA_R_DIRECT flags set
|
||||
* we need to call ata_complete() directly here (no taskqueue involvement)
|
||||
*/
|
||||
if (dumping ||
|
||||
(ch->state & ATA_STALL_QUEUE) || (request->flags & ATA_R_DIRECT)) {
|
||||
if (dumping) {
|
||||
ATA_DEBUG_RQ(request, "finish directly");
|
||||
ata_completed(request, 0);
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ ata_raid_flush(struct bio *bp)
|
||||
request->u.ata.feature = 0;
|
||||
request->timeout = 1;
|
||||
request->retries = 0;
|
||||
request->flags |= ATA_R_ORDERED | ATA_R_DIRECT;
|
||||
request->flags |= ATA_R_ORDERED | ATA_R_THREAD;
|
||||
ata_queue_request(request);
|
||||
}
|
||||
return 0;
|
||||
@ -1570,7 +1570,7 @@ ata_raid_wipe_metadata(struct ar_softc *rdp)
|
||||
if (!(meta = malloc(size, M_AR, M_NOWAIT | M_ZERO)))
|
||||
return ENOMEM;
|
||||
if (ata_raid_rw(rdp->disks[disk].dev, lba, meta, size,
|
||||
ATA_R_WRITE | ATA_R_DIRECT)) {
|
||||
ATA_R_WRITE | ATA_R_THREAD)) {
|
||||
device_printf(rdp->disks[disk].dev, "wipe metadata failed\n");
|
||||
error = EIO;
|
||||
}
|
||||
@ -2264,7 +2264,7 @@ ata_raid_hptv2_write_meta(struct ar_softc *rdp)
|
||||
if (ata_raid_rw(rdp->disks[disk].dev,
|
||||
HPTV2_LBA(rdp->disks[disk].dev), meta,
|
||||
sizeof(struct promise_raid_conf),
|
||||
ATA_R_WRITE | ATA_R_DIRECT)) {
|
||||
ATA_R_WRITE | ATA_R_THREAD)) {
|
||||
device_printf(rdp->disks[disk].dev, "write metadata failed\n");
|
||||
error = EIO;
|
||||
}
|
||||
@ -2710,7 +2710,7 @@ ata_raid_intel_write_meta(struct ar_softc *rdp)
|
||||
if (rdp->disks[disk].dev) {
|
||||
if (ata_raid_rw(rdp->disks[disk].dev,
|
||||
INTEL_LBA(rdp->disks[disk].dev),
|
||||
meta, 1024, ATA_R_WRITE | ATA_R_DIRECT)) {
|
||||
meta, 1024, ATA_R_WRITE | ATA_R_THREAD)) {
|
||||
device_printf(rdp->disks[disk].dev, "write metadata failed\n");
|
||||
error = EIO;
|
||||
}
|
||||
@ -3055,7 +3055,7 @@ ata_raid_jmicron_write_meta(struct ar_softc *rdp)
|
||||
if (ata_raid_rw(rdp->disks[disk].dev,
|
||||
JMICRON_LBA(rdp->disks[disk].dev),
|
||||
meta, sizeof(struct jmicron_raid_conf),
|
||||
ATA_R_WRITE | ATA_R_DIRECT)) {
|
||||
ATA_R_WRITE | ATA_R_THREAD)) {
|
||||
device_printf(rdp->disks[disk].dev, "write metadata failed\n");
|
||||
error = EIO;
|
||||
}
|
||||
@ -3778,7 +3778,7 @@ ata_raid_promise_write_meta(struct ar_softc *rdp)
|
||||
if (ata_raid_rw(rdp->disks[disk].dev,
|
||||
PROMISE_LBA(rdp->disks[disk].dev),
|
||||
meta, sizeof(struct promise_raid_conf),
|
||||
ATA_R_WRITE | ATA_R_DIRECT)) {
|
||||
ATA_R_WRITE | ATA_R_THREAD)) {
|
||||
device_printf(rdp->disks[disk].dev, "write metadata failed\n");
|
||||
error = EIO;
|
||||
}
|
||||
@ -4126,7 +4126,7 @@ ata_raid_sis_write_meta(struct ar_softc *rdp)
|
||||
if (ata_raid_rw(rdp->disks[disk].dev,
|
||||
SIS_LBA(rdp->disks[disk].dev),
|
||||
meta, sizeof(struct sis_raid_conf),
|
||||
ATA_R_WRITE | ATA_R_DIRECT)) {
|
||||
ATA_R_WRITE | ATA_R_THREAD)) {
|
||||
device_printf(rdp->disks[disk].dev, "write metadata failed\n");
|
||||
error = EIO;
|
||||
}
|
||||
@ -4351,7 +4351,7 @@ ata_raid_via_write_meta(struct ar_softc *rdp)
|
||||
if (ata_raid_rw(rdp->disks[disk].dev,
|
||||
VIA_LBA(rdp->disks[disk].dev),
|
||||
meta, sizeof(struct via_raid_conf),
|
||||
ATA_R_WRITE | ATA_R_DIRECT)) {
|
||||
ATA_R_WRITE | ATA_R_THREAD)) {
|
||||
device_printf(rdp->disks[disk].dev, "write metadata failed\n");
|
||||
error = EIO;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user