summaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-probe.c
diff options
context:
space:
mode:
authorJens Axboe2019-01-30 16:41:40 +0100
committerJens Axboe2019-01-31 16:25:09 +0100
commit9a6d5488002fdca7134a0e59b0ae252f61042810 (patch)
treeda65822cbac6defce676db665ea2ffb4cb89903b /drivers/ide/ide-probe.c
parentblk-mq: fix a hung issue when fsync (diff)
downloadkernel-qcow2-linux-9a6d5488002fdca7134a0e59b0ae252f61042810.tar.gz
kernel-qcow2-linux-9a6d5488002fdca7134a0e59b0ae252f61042810.tar.xz
kernel-qcow2-linux-9a6d5488002fdca7134a0e59b0ae252f61042810.zip
ide: ensure atapi sense request aren't preempted
There's an issue with how sense requests are handled in IDE. If ide-cd encounters an error, it queues a sense request. With how IDE request handling is done, this is the next request we need to handle. But it's impossible to guarantee this, as another request could come in between the sense being queued, and ->queue_rq() being run and handling it. If that request ALSO fails, then we attempt to doubly queue the single sense request we have. Since we only support one active request at the time, defer request processing when a sense request is queued. Fixes: 600335205b8d "ide: convert to blk-mq" Reported-by: He Zhe <zhe.he@windriver.com> Tested-by: He Zhe <zhe.he@windriver.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r--drivers/ide/ide-probe.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 63627be0811a..5aeaca24a28f 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1159,18 +1159,27 @@ static void drive_rq_insert_work(struct work_struct *work)
ide_drive_t *drive = container_of(work, ide_drive_t, rq_work);
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
+ blk_status_t ret;
LIST_HEAD(list);
- spin_lock_irq(&hwif->lock);
- if (!list_empty(&drive->rq_list))
- list_splice_init(&drive->rq_list, &list);
- spin_unlock_irq(&hwif->lock);
+ blk_mq_quiesce_queue(drive->queue);
- while (!list_empty(&list)) {
- rq = list_first_entry(&list, struct request, queuelist);
+ ret = BLK_STS_OK;
+ spin_lock_irq(&hwif->lock);
+ while (!list_empty(&drive->rq_list)) {
+ rq = list_first_entry(&drive->rq_list, struct request, queuelist);
list_del_init(&rq->queuelist);
- blk_execute_rq_nowait(drive->queue, rq->rq_disk, rq, true, NULL);
+
+ spin_unlock_irq(&hwif->lock);
+ ret = ide_issue_rq(drive, rq, true);
+ spin_lock_irq(&hwif->lock);
}
+ spin_unlock_irq(&hwif->lock);
+
+ blk_mq_unquiesce_queue(drive->queue);
+
+ if (ret != BLK_STS_OK)
+ kblockd_schedule_work(&drive->rq_work);
}
static const u8 ide_hwif_to_major[] =