|
@@ -1117,6 +1117,42 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Suspend virtqueue ioeventfd processing during drain */
|
|
|
|
+static void virtio_scsi_drained_begin(SCSIBus *bus)
|
|
|
|
+{
|
|
|
|
+ VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
|
|
|
|
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
|
|
|
+ uint32_t total_queues = VIRTIO_SCSI_VQ_NUM_FIXED +
|
|
|
|
+ s->parent_obj.conf.num_queues;
|
|
|
|
+
|
|
|
|
+ if (!s->dataplane_started) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (uint32_t i = 0; i < total_queues; i++) {
|
|
|
|
+ VirtQueue *vq = virtio_get_queue(vdev, i);
|
|
|
|
+ virtio_queue_aio_detach_host_notifier(vq, s->ctx);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Resume virtqueue ioeventfd processing after drain */
|
|
|
|
+static void virtio_scsi_drained_end(SCSIBus *bus)
|
|
|
|
+{
|
|
|
|
+ VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
|
|
|
|
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
|
|
|
+ uint32_t total_queues = VIRTIO_SCSI_VQ_NUM_FIXED +
|
|
|
|
+ s->parent_obj.conf.num_queues;
|
|
|
|
+
|
|
|
|
+ if (!s->dataplane_started) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (uint32_t i = 0; i < total_queues; i++) {
|
|
|
|
+ VirtQueue *vq = virtio_get_queue(vdev, i);
|
|
|
|
+ virtio_queue_aio_attach_host_notifier(vq, s->ctx);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static struct SCSIBusInfo virtio_scsi_scsi_info = {
|
|
static struct SCSIBusInfo virtio_scsi_scsi_info = {
|
|
.tcq = true,
|
|
.tcq = true,
|
|
.max_channel = VIRTIO_SCSI_MAX_CHANNEL,
|
|
.max_channel = VIRTIO_SCSI_MAX_CHANNEL,
|
|
@@ -1131,6 +1167,8 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
|
|
.get_sg_list = virtio_scsi_get_sg_list,
|
|
.get_sg_list = virtio_scsi_get_sg_list,
|
|
.save_request = virtio_scsi_save_request,
|
|
.save_request = virtio_scsi_save_request,
|
|
.load_request = virtio_scsi_load_request,
|
|
.load_request = virtio_scsi_load_request,
|
|
|
|
+ .drained_begin = virtio_scsi_drained_begin,
|
|
|
|
+ .drained_end = virtio_scsi_drained_end,
|
|
};
|
|
};
|
|
|
|
|
|
void virtio_scsi_common_realize(DeviceState *dev,
|
|
void virtio_scsi_common_realize(DeviceState *dev,
|