virtio-blk has been converted to use the threadpool.
All the threading code has been removed, which left only simple callback 
handling code.

New threadpool job types are created within VIRTIO_PCI_QUEUE_PFN for every 
queue (just one in the case of virtio-blk).
The module signals for work after receiving VIRTIO_PCI_QUEUE_NOTIFY and expects 
the threadpool to call virtio_blk_do_io to handle the I/O.
It is possible that the module will signal work several times while 
virtio_blk_do_io is already working, but there is no need to handle 
multithreading there since the threadpool will call each job in linear and not 
in parallel.

Signed-off-by: Sasha Levin <[email protected]>
---
 tools/kvm/virtio-blk.c |   86 +++++++-----------------------------------------
 1 files changed, 12 insertions(+), 74 deletions(-)

diff --git a/tools/kvm/virtio-blk.c b/tools/kvm/virtio-blk.c
index 3516b1c..3feabd0 100644
--- a/tools/kvm/virtio-blk.c
+++ b/tools/kvm/virtio-blk.c
@@ -9,6 +9,7 @@
 #include "kvm/util.h"
 #include "kvm/kvm.h"
 #include "kvm/pci.h"
+#include "kvm/threadpool.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_blk.h>
@@ -31,15 +32,13 @@ struct blk_device {
        uint32_t                        guest_features;
        uint16_t                        config_vector;
        uint8_t                         status;
-       pthread_t                       io_thread;
-       pthread_mutex_t         io_mutex;
-       pthread_cond_t          io_cond;
 
        /* virtio queue */
        uint16_t                        queue_selector;
-       uint64_t                        virtio_blk_queue_set_flags;
 
        struct virt_queue               vqs[NUM_VIRT_QUEUES];
+
+       void                    *jobs[NUM_VIRT_QUEUES];
 };
 
 #define DISK_SEG_MAX   126
@@ -57,9 +56,6 @@ static struct blk_device blk_device = {
         * same applies to VIRTIO_BLK_F_BLK_SIZE
         */
        .host_features          = (1UL << VIRTIO_BLK_F_SEG_MAX),
-
-       .io_mutex                       = PTHREAD_MUTEX_INITIALIZER,
-       .io_cond                        = PTHREAD_COND_INITIALIZER
 };
 
 static bool virtio_blk_pci_io_device_specific_in(void *data, unsigned long 
offset, int size, uint32_t count)
@@ -156,73 +152,14 @@ static bool virtio_blk_do_io_request(struct kvm *self, 
struct virt_queue *queue)
        return true;
 }
 
-
-
-static int virtio_blk_get_selected_queue(struct blk_device *dev)
-{
-       int i;
-
-       for (i = 0 ; i < NUM_VIRT_QUEUES ; i++) {
-               if (dev->virtio_blk_queue_set_flags & (1 << i)) {
-                       dev->virtio_blk_queue_set_flags &= ~(1 << i);
-                       return i;
-               }
-       }
-
-       return -1;
-}
-
-static void virtio_blk_do_io(struct kvm *kvm, struct blk_device *dev)
+static void virtio_blk_do_io(struct kvm *kvm, void *param)
 {
-       for (;;) {
-               struct virt_queue *vq;
-               int queue_index;
-
-               mutex_lock(&dev->io_mutex);
-               queue_index = virtio_blk_get_selected_queue(dev);
-               mutex_unlock(&dev->io_mutex);
-
-               if (queue_index < 0)
-                       break;
+       struct virt_queue *vq = param;
 
-               vq = &dev->vqs[queue_index];
+       while (virt_queue__available(vq))
+               virtio_blk_do_io_request(kvm, vq);
 
-               while (virt_queue__available(vq))
-                       virtio_blk_do_io_request(kvm, vq);
-
-               kvm__irq_line(kvm, VIRTIO_BLK_IRQ, 1);
-       }
-}
-
-static void *virtio_blk_io_thread(void *ptr)
-{
-       struct kvm *self = ptr;
-
-       for (;;) {
-               int ret;
-
-               mutex_lock(&blk_device.io_mutex);
-               ret = pthread_cond_wait(&blk_device.io_cond, 
&blk_device.io_mutex);
-               mutex_unlock(&blk_device.io_mutex);
-
-               if (ret != 0)
-                       break;
-
-               virtio_blk_do_io(self, &blk_device);
-       }
-
-       return NULL;
-}
-
-static void virtio_blk_handle_callback(struct blk_device *dev, uint16_t 
queue_index)
-{
-       mutex_lock(&dev->io_mutex);
-
-       dev->virtio_blk_queue_set_flags |= (1 << queue_index);
-
-       mutex_unlock(&dev->io_mutex);
-
-       pthread_cond_signal(&dev->io_cond);
+       kvm__irq_line(kvm, VIRTIO_BLK_IRQ, 1);
 }
 
 static bool virtio_blk_pci_io_out(struct kvm *self, uint16_t port, void *data, 
int size, uint32_t count)
@@ -250,6 +187,9 @@ static bool virtio_blk_pci_io_out(struct kvm *self, 
uint16_t port, void *data, i
 
                vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, 4096);
 
+               blk_device.jobs[blk_device.queue_selector] =
+                       thread_pool__add_jobtype(self, virtio_blk_do_io, queue);
+
                break;
        }
        case VIRTIO_PCI_QUEUE_SEL:
@@ -258,7 +198,7 @@ static bool virtio_blk_pci_io_out(struct kvm *self, 
uint16_t port, void *data, i
        case VIRTIO_PCI_QUEUE_NOTIFY: {
                uint16_t queue_index;
                queue_index             = ioport__read16(data);
-               virtio_blk_handle_callback(&blk_device, queue_index);
+               thread_pool__signal_work(blk_device.jobs[queue_index]);
                break;
        }
        case VIRTIO_PCI_STATUS:
@@ -308,8 +248,6 @@ void virtio_blk__init(struct kvm *self)
        if (!self->disk_image)
                return;
 
-       pthread_create(&blk_device.io_thread, NULL, virtio_blk_io_thread, self);
-
        blk_device.blk_config.capacity = self->disk_image->size / SECTOR_SIZE;
 
        pci__register(&virtio_blk_pci_device, PCI_VIRTIO_BLK_DEVNUM);
-- 
1.7.5.rc3

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to