virtio-scsi-dataplane.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Virtio SCSI dataplane
  3. *
  4. * Copyright Red Hat, Inc. 2014
  5. *
  6. * Authors:
  7. * Fam Zheng <famz@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10. * See the COPYING file in the top-level directory.
  11. *
  12. */
  13. #include "qemu/osdep.h"
  14. #include "qapi/error.h"
  15. #include "hw/virtio/virtio-scsi.h"
  16. #include "qemu/error-report.h"
  17. #include "sysemu/block-backend.h"
  18. #include "hw/scsi/scsi.h"
  19. #include "scsi/constants.h"
  20. #include "hw/virtio/virtio-bus.h"
  21. #include "hw/virtio/virtio-access.h"
  22. /* Context: QEMU global mutex held */
  23. void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp)
  24. {
  25. VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
  26. VirtIODevice *vdev = VIRTIO_DEVICE(s);
  27. BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
  28. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
  29. if (vs->conf.iothread) {
  30. if (!k->set_guest_notifiers || !k->ioeventfd_assign) {
  31. error_setg(errp,
  32. "device is incompatible with iothread "
  33. "(transport does not support notifiers)");
  34. return;
  35. }
  36. if (!virtio_device_ioeventfd_enabled(vdev)) {
  37. error_setg(errp, "ioeventfd is required for iothread");
  38. return;
  39. }
  40. s->ctx = iothread_get_aio_context(vs->conf.iothread);
  41. } else {
  42. if (!virtio_device_ioeventfd_enabled(vdev)) {
  43. return;
  44. }
  45. s->ctx = qemu_get_aio_context();
  46. }
  47. }
  48. static int virtio_scsi_set_host_notifier(VirtIOSCSI *s, VirtQueue *vq, int n)
  49. {
  50. BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
  51. int rc;
  52. /* Set up virtqueue notify */
  53. rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), n, true);
  54. if (rc != 0) {
  55. fprintf(stderr, "virtio-scsi: Failed to set host notifier (%d)\n",
  56. rc);
  57. s->dataplane_fenced = true;
  58. return rc;
  59. }
  60. return 0;
  61. }
  62. /* Context: BH in IOThread */
  63. static void virtio_scsi_dataplane_stop_bh(void *opaque)
  64. {
  65. VirtIOSCSI *s = opaque;
  66. VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
  67. int i;
  68. virtio_queue_aio_detach_host_notifier(vs->ctrl_vq, s->ctx);
  69. virtio_queue_aio_detach_host_notifier(vs->event_vq, s->ctx);
  70. for (i = 0; i < vs->conf.num_queues; i++) {
  71. virtio_queue_aio_detach_host_notifier(vs->cmd_vqs[i], s->ctx);
  72. }
  73. }
  74. /* Context: QEMU global mutex held */
  75. int virtio_scsi_dataplane_start(VirtIODevice *vdev)
  76. {
  77. int i;
  78. int rc;
  79. int vq_init_count = 0;
  80. BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
  81. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
  82. VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
  83. VirtIOSCSI *s = VIRTIO_SCSI(vdev);
  84. if (s->dataplane_started ||
  85. s->dataplane_starting ||
  86. s->dataplane_fenced) {
  87. return 0;
  88. }
  89. s->dataplane_starting = true;
  90. /* Set up guest notifier (irq) */
  91. rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true);
  92. if (rc != 0) {
  93. error_report("virtio-scsi: Failed to set guest notifiers (%d), "
  94. "ensure -accel kvm is set.", rc);
  95. goto fail_guest_notifiers;
  96. }
  97. /*
  98. * Batch all the host notifiers in a single transaction to avoid
  99. * quadratic time complexity in address_space_update_ioeventfds().
  100. */
  101. memory_region_transaction_begin();
  102. rc = virtio_scsi_set_host_notifier(s, vs->ctrl_vq, 0);
  103. if (rc != 0) {
  104. goto fail_host_notifiers;
  105. }
  106. vq_init_count++;
  107. rc = virtio_scsi_set_host_notifier(s, vs->event_vq, 1);
  108. if (rc != 0) {
  109. goto fail_host_notifiers;
  110. }
  111. vq_init_count++;
  112. for (i = 0; i < vs->conf.num_queues; i++) {
  113. rc = virtio_scsi_set_host_notifier(s, vs->cmd_vqs[i], i + 2);
  114. if (rc) {
  115. goto fail_host_notifiers;
  116. }
  117. vq_init_count++;
  118. }
  119. memory_region_transaction_commit();
  120. /*
  121. * These fields are visible to the IOThread so we rely on implicit barriers
  122. * in aio_context_acquire() on the write side and aio_notify_accept() on
  123. * the read side.
  124. */
  125. s->dataplane_starting = false;
  126. s->dataplane_started = true;
  127. aio_context_acquire(s->ctx);
  128. virtio_queue_aio_attach_host_notifier(vs->ctrl_vq, s->ctx);
  129. virtio_queue_aio_attach_host_notifier_no_poll(vs->event_vq, s->ctx);
  130. for (i = 0; i < vs->conf.num_queues; i++) {
  131. virtio_queue_aio_attach_host_notifier(vs->cmd_vqs[i], s->ctx);
  132. }
  133. aio_context_release(s->ctx);
  134. return 0;
  135. fail_host_notifiers:
  136. for (i = 0; i < vq_init_count; i++) {
  137. virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
  138. }
  139. /*
  140. * The transaction expects the ioeventfds to be open when it
  141. * commits. Do it now, before the cleanup loop.
  142. */
  143. memory_region_transaction_commit();
  144. for (i = 0; i < vq_init_count; i++) {
  145. virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
  146. }
  147. k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);
  148. fail_guest_notifiers:
  149. s->dataplane_fenced = true;
  150. s->dataplane_starting = false;
  151. s->dataplane_started = true;
  152. return -ENOSYS;
  153. }
  154. /* Context: QEMU global mutex held */
  155. void virtio_scsi_dataplane_stop(VirtIODevice *vdev)
  156. {
  157. BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
  158. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
  159. VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
  160. VirtIOSCSI *s = VIRTIO_SCSI(vdev);
  161. int i;
  162. if (!s->dataplane_started || s->dataplane_stopping) {
  163. return;
  164. }
  165. /* Better luck next time. */
  166. if (s->dataplane_fenced) {
  167. s->dataplane_fenced = false;
  168. s->dataplane_started = false;
  169. return;
  170. }
  171. s->dataplane_stopping = true;
  172. aio_context_acquire(s->ctx);
  173. aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s);
  174. aio_context_release(s->ctx);
  175. blk_drain_all(); /* ensure there are no in-flight requests */
  176. /*
  177. * Batch all the host notifiers in a single transaction to avoid
  178. * quadratic time complexity in address_space_update_ioeventfds().
  179. */
  180. memory_region_transaction_begin();
  181. for (i = 0; i < vs->conf.num_queues + 2; i++) {
  182. virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
  183. }
  184. /*
  185. * The transaction expects the ioeventfds to be open when it
  186. * commits. Do it now, before the cleanup loop.
  187. */
  188. memory_region_transaction_commit();
  189. for (i = 0; i < vs->conf.num_queues + 2; i++) {
  190. virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
  191. }
  192. /* Clean up guest notifier (irq) */
  193. k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);
  194. s->dataplane_stopping = false;
  195. s->dataplane_started = false;
  196. }