Skip to content

Commit b5b6e8c

Browse files
Ming Leimartinkpetersen
authored andcommitted
scsi: virtio_scsi: fix IO hang caused by automatic irq vector affinity
Since commit 84676c1 ("genirq/affinity: assign vectors to all possible CPUs") it is possible to end up in a scenario where only offline CPUs are mapped to an interrupt vector. This is only an issue for the legacy I/O path since with blk-mq/scsi-mq an I/O can't be submitted to a hardware queue if the queue isn't mapped to an online CPU. Fix this issue by forcing virtio-scsi to use blk-mq. [mkp: commit desc] Cc: Omar Sandoval <osandov@fb.com>, Cc: "Martin K. Petersen" <martin.petersen@oracle.com>, Cc: James Bottomley <james.bottomley@hansenpartnership.com>, Cc: Christoph Hellwig <hch@lst.de>, Cc: Don Brace <don.brace@microsemi.com> Cc: Kashyap Desai <kashyap.desai@broadcom.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Mike Snitzer <snitzer@redhat.com> Cc: Laurence Oberman <loberman@redhat.com> Fixes: 84676c1 ("genirq/affinity: assign vectors to all possible CPUs") Signed-off-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Acked-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 2f31115 commit b5b6e8c

File tree

1 file changed

+3
-56
lines changed

1 file changed

+3
-56
lines changed

drivers/scsi/virtio_scsi.c

Lines changed: 3 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,6 @@ struct virtio_scsi_vq {
9191
struct virtio_scsi_target_state {
9292
seqcount_t tgt_seq;
9393

94-
/* Count of outstanding requests. */
95-
atomic_t reqs;
96-
9794
/* Currently active virtqueue for requests sent to this target. */
9895
struct virtio_scsi_vq *req_vq;
9996
};
@@ -152,8 +149,6 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
152149
struct virtio_scsi_cmd *cmd = buf;
153150
struct scsi_cmnd *sc = cmd->sc;
154151
struct virtio_scsi_cmd_resp *resp = &cmd->resp.cmd;
155-
struct virtio_scsi_target_state *tgt =
156-
scsi_target(sc->device)->hostdata;
157152

158153
dev_dbg(&sc->device->sdev_gendev,
159154
"cmd %p response %u status %#02x sense_len %u\n",
@@ -210,8 +205,6 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
210205
}
211206

212207
sc->scsi_done(sc);
213-
214-
atomic_dec(&tgt->reqs);
215208
}
216209

217210
static void virtscsi_vq_done(struct virtio_scsi *vscsi,
@@ -580,10 +573,7 @@ static int virtscsi_queuecommand_single(struct Scsi_Host *sh,
580573
struct scsi_cmnd *sc)
581574
{
582575
struct virtio_scsi *vscsi = shost_priv(sh);
583-
struct virtio_scsi_target_state *tgt =
584-
scsi_target(sc->device)->hostdata;
585576

586-
atomic_inc(&tgt->reqs);
587577
return virtscsi_queuecommand(vscsi, &vscsi->req_vqs[0], sc);
588578
}
589579

@@ -596,55 +586,11 @@ static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi,
596586
return &vscsi->req_vqs[hwq];
597587
}
598588

599-
static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi,
600-
struct virtio_scsi_target_state *tgt)
601-
{
602-
struct virtio_scsi_vq *vq;
603-
unsigned long flags;
604-
u32 queue_num;
605-
606-
local_irq_save(flags);
607-
if (atomic_inc_return(&tgt->reqs) > 1) {
608-
unsigned long seq;
609-
610-
do {
611-
seq = read_seqcount_begin(&tgt->tgt_seq);
612-
vq = tgt->req_vq;
613-
} while (read_seqcount_retry(&tgt->tgt_seq, seq));
614-
} else {
615-
/* no writes can be concurrent because of atomic_t */
616-
write_seqcount_begin(&tgt->tgt_seq);
617-
618-
/* keep previous req_vq if a reader just arrived */
619-
if (unlikely(atomic_read(&tgt->reqs) > 1)) {
620-
vq = tgt->req_vq;
621-
goto unlock;
622-
}
623-
624-
queue_num = smp_processor_id();
625-
while (unlikely(queue_num >= vscsi->num_queues))
626-
queue_num -= vscsi->num_queues;
627-
tgt->req_vq = vq = &vscsi->req_vqs[queue_num];
628-
unlock:
629-
write_seqcount_end(&tgt->tgt_seq);
630-
}
631-
local_irq_restore(flags);
632-
633-
return vq;
634-
}
635-
636589
static int virtscsi_queuecommand_multi(struct Scsi_Host *sh,
637590
struct scsi_cmnd *sc)
638591
{
639592
struct virtio_scsi *vscsi = shost_priv(sh);
640-
struct virtio_scsi_target_state *tgt =
641-
scsi_target(sc->device)->hostdata;
642-
struct virtio_scsi_vq *req_vq;
643-
644-
if (shost_use_blk_mq(sh))
645-
req_vq = virtscsi_pick_vq_mq(vscsi, sc);
646-
else
647-
req_vq = virtscsi_pick_vq(vscsi, tgt);
593+
struct virtio_scsi_vq *req_vq = virtscsi_pick_vq_mq(vscsi, sc);
648594

649595
return virtscsi_queuecommand(vscsi, req_vq, sc);
650596
}
@@ -775,7 +721,6 @@ static int virtscsi_target_alloc(struct scsi_target *starget)
775721
return -ENOMEM;
776722

777723
seqcount_init(&tgt->tgt_seq);
778-
atomic_set(&tgt->reqs, 0);
779724
tgt->req_vq = &vscsi->req_vqs[0];
780725

781726
starget->hostdata = tgt;
@@ -823,6 +768,7 @@ static struct scsi_host_template virtscsi_host_template_single = {
823768
.target_alloc = virtscsi_target_alloc,
824769
.target_destroy = virtscsi_target_destroy,
825770
.track_queue_depth = 1,
771+
.force_blk_mq = 1,
826772
};
827773

828774
static struct scsi_host_template virtscsi_host_template_multi = {
@@ -844,6 +790,7 @@ static struct scsi_host_template virtscsi_host_template_multi = {
844790
.target_destroy = virtscsi_target_destroy,
845791
.map_queues = virtscsi_map_queues,
846792
.track_queue_depth = 1,
793+
.force_blk_mq = 1,
847794
};
848795

849796
#define virtscsi_config_get(vdev, fld) \

0 commit comments

Comments
 (0)