Commit e67423c7 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Rusty Russell
Browse files

virtio_scsi: fix race on device removal



We cancel event work on device removal, but an interrupt
could trigger immediately after this, and queue it
again.

To fix, set a flag.

Loosely based on patch by Paolo Bonzini

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 1fa5b2a7
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -110,6 +110,9 @@ struct virtio_scsi {
	/* CPU hotplug notifier */
	struct notifier_block nb;

	/* Protected by event_vq lock */
	bool stop_events;

	struct virtio_scsi_vq ctrl_vq;
	struct virtio_scsi_vq event_vq;
	struct virtio_scsi_vq req_vqs[];
@@ -303,6 +306,11 @@ static void virtscsi_cancel_event_work(struct virtio_scsi *vscsi)
{
	int i;

	/* Stop scheduling work before calling cancel_work_sync.  */
	spin_lock_irq(&vscsi->event_vq.vq_lock);
	vscsi->stop_events = true;
	spin_unlock_irq(&vscsi->event_vq.vq_lock);

	for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++)
		cancel_work_sync(&vscsi->event_list[i].work);
}
@@ -390,6 +398,7 @@ static void virtscsi_complete_event(struct virtio_scsi *vscsi, void *buf)
{
	struct virtio_scsi_event_node *event_node = buf;

	if (!vscsi->stop_events)
		queue_work(system_freezable_wq, &event_node->work);
}