Re: [Qemu-block] [PATCH v5 06/13] virtio-scsi-dataplane: Add device IO op blocker listener

2015-05-23 Thread Max Reitz

On 20.05.2015 08:16, Fam Zheng wrote:

When a disk is attached to scsi-bus, virtio_scsi_hotplug will take care
of protecting the block device with op blockers. Currently we haven't
enabled block jobs (like what's done in virtio_blk_data_plane_create),
but it is necessary to honor device IO op blocker first before we do.
This is useful to make sure that guest IO requests are paused during qmp
transactions (such as multi-disk snapshot or backup).

A counter is added to the virtio-scsi device, which keeps track of
currently blocked disks. If it goes from 0 to 1, the ioeventfds are
disabled; when it goes back to 0, they are re-enabled.

Also in device initialization, push the enabling of ioeventfds to before
return, so the virtio_scsi_clear_aio is not needed there. Rename it,
pair with an enabling variant, fix one coding style issue, then use it
in the device pause points.

Signed-off-by: Fam Zheng f...@redhat.com
---
  hw/scsi/virtio-scsi-dataplane.c | 82 +++--
  hw/scsi/virtio-scsi.c   |  3 ++
  include/hw/virtio/virtio-scsi.h |  3 ++
  3 files changed, 68 insertions(+), 20 deletions(-)


Reviewed-by: Max Reitz mre...@redhat.com



[Qemu-block] [PATCH v5 06/13] virtio-scsi-dataplane: Add device IO op blocker listener

2015-05-20 Thread Fam Zheng
When a disk is attached to scsi-bus, virtio_scsi_hotplug will take care
of protecting the block device with op blockers. Currently we haven't
enabled block jobs (like what's done in virtio_blk_data_plane_create),
but it is necessary to honor device IO op blocker first before we do.
This is useful to make sure that guest IO requests are paused during qmp
transactions (such as multi-disk snapshot or backup).

A counter is added to the virtio-scsi device, which keeps track of
currently blocked disks. If it goes from 0 to 1, the ioeventfds are
disabled; when it goes back to 0, they are re-enabled.

Also in device initialization, push the enabling of ioeventfds to before
return, so the virtio_scsi_clear_aio is not needed there. Rename it,
pair with an enabling variant, fix one coding style issue, then use it
in the device pause points.

Signed-off-by: Fam Zheng f...@redhat.com
---
 hw/scsi/virtio-scsi-dataplane.c | 82 +++--
 hw/scsi/virtio-scsi.c   |  3 ++
 include/hw/virtio/virtio-scsi.h |  3 ++
 3 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 5575648..e220c12 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -40,7 +40,6 @@ void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread 
*iothread)
 
 static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
VirtQueue *vq,
-   EventNotifierHandler *handler,
int n)
 {
 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
@@ -60,7 +59,6 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
 r = g_slice_new(VirtIOSCSIVring);
 r-host_notifier = *virtio_queue_get_host_notifier(vq);
 r-guest_notifier = *virtio_queue_get_guest_notifier(vq);
-aio_set_event_notifier(s-ctx, r-host_notifier, handler);
 
 r-parent = s;
 
@@ -71,7 +69,6 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
 return r;
 
 fail_vring:
-aio_set_event_notifier(s-ctx, r-host_notifier, NULL);
 k-set_host_notifier(qbus-parent, n, false);
 g_slice_free(VirtIOSCSIVring, r);
 return NULL;
@@ -104,6 +101,9 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
 }
 }
 
+static void virtio_scsi_start_ioeventfd(VirtIOSCSI *s);
+static void virtio_scsi_stop_ioeventfd(VirtIOSCSI *s);
+
 static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
 {
 VirtIOSCSIVring *vring = container_of(notifier,
@@ -111,6 +111,7 @@ static void virtio_scsi_iothread_handle_ctrl(EventNotifier 
*notifier)
 VirtIOSCSI *s = VIRTIO_SCSI(vring-parent);
 VirtIOSCSIReq *req;
 
+assert(!s-pause_counter);
 event_notifier_test_and_clear(notifier);
 while ((req = virtio_scsi_pop_req_vring(s, vring))) {
 virtio_scsi_handle_ctrl_req(s, req);
@@ -124,6 +125,7 @@ static void virtio_scsi_iothread_handle_event(EventNotifier 
*notifier)
 VirtIOSCSI *s = vring-parent;
 VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
+assert(!s-pause_counter);
 event_notifier_test_and_clear(notifier);
 
 if (!(vdev-status  VIRTIO_CONFIG_S_DRIVER_OK)) {
@@ -143,6 +145,7 @@ static void virtio_scsi_iothread_handle_cmd(EventNotifier 
*notifier)
 VirtIOSCSIReq *req, *next;
 QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
 
+assert(!s-pause_counter);
 event_notifier_test_and_clear(notifier);
 while ((req = virtio_scsi_pop_req_vring(s, vring))) {
 if (virtio_scsi_handle_cmd_req_prepare(s, req)) {
@@ -155,8 +158,56 @@ static void virtio_scsi_iothread_handle_cmd(EventNotifier 
*notifier)
 }
 }
 
+void virtio_scsi_dataplane_blocker_notify(Notifier *notifier,
+  void *data)
+{
+VirtIOSCSI *s = container_of(notifier, VirtIOSCSI, blocker_notifier);
+BlockOpEvent *event = data;
+
+if (event-type != BLOCK_OP_TYPE_DEVICE_IO) {
+return;
+}
+if (event-blocking) {
+s-pause_counter++;
+if (s-pause_counter == 1) {
+virtio_scsi_stop_ioeventfd(s);
+}
+} else {
+s-pause_counter--;
+if (s-pause_counter == 0) {
+virtio_scsi_start_ioeventfd(s);
+}
+}
+assert(s-pause_counter = 0);
+}
+
 /* assumes s-ctx held */
-static void virtio_scsi_clear_aio(VirtIOSCSI *s)
+static void virtio_scsi_start_ioeventfd(VirtIOSCSI *s)
+{
+VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
+int i;
+
+if (!s-dataplane_started || s-dataplane_stopping) {
+return;
+}
+if (s-ctrl_vring) {
+aio_set_event_notifier(s-ctx, s-ctrl_vring-host_notifier,
+   virtio_scsi_iothread_handle_ctrl);
+}
+if (s-event_vring) {
+aio_set_event_notifier(s-ctx, s-event_vring-host_notifier,
+