]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Use virt_queue__get_iov to simpify virtio blk IO handler
authorAsias He <asias.hejun@gmail.com>
Fri, 8 Apr 2011 16:10:07 +0000 (00:10 +0800)
committerPekka Enberg <penberg@kernel.org>
Fri, 8 Apr 2011 16:22:01 +0000 (19:22 +0300)
This really makes my life much easier!

Signed-off-by: Asias He <asias.hejun@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/virtio-blk.c

index 8351e7ada5f4bf1c5fe80f39d3539330f1773924..b61b9d43b04f2ff8b7ba470d9ba467de4e752554 100644 (file)
@@ -30,7 +30,7 @@ struct blk_device {
        /* virtio queue */
        uint16_t                        queue_selector;
 
-       struct virt_queue               virt_queues[NUM_VIRT_QUEUES];
+       struct virt_queue               vqs[NUM_VIRT_QUEUES];
 };
 
 #define DISK_SEG_MAX   126
@@ -73,7 +73,7 @@ static bool virtio_blk_pci_io_in(struct kvm *self, uint16_t port, void *data, in
        case VIRTIO_PCI_GUEST_FEATURES:
                return false;
        case VIRTIO_PCI_QUEUE_PFN:
-               ioport__write32(data, blk_device.virt_queues[blk_device.queue_selector].pfn);
+               ioport__write32(data, blk_device.vqs[blk_device.queue_selector].pfn);
                break;
        case VIRTIO_PCI_QUEUE_NUM:
                ioport__write16(data, VIRTIO_BLK_QUEUE_SIZE);
@@ -98,66 +98,29 @@ static bool virtio_blk_pci_io_in(struct kvm *self, uint16_t port, void *data, in
        return true;
 }
 
-static bool virtio_blk_request(struct kvm *self, struct virt_queue *queue)
+static bool virtio_blk_do_io_request(struct kvm *self, struct virt_queue *queue)
 {
+
+       struct iovec iov[VIRTIO_BLK_QUEUE_SIZE];
        struct virtio_blk_outhdr *req;
-       uint16_t desc_block_last;
-       struct vring_desc *desc;
-       uint16_t desc_status;
-       uint16_t desc_block;
-       uint32_t block_len;
-       uint32_t block_cnt;
-       uint16_t desc_hdr;
+       uint32_t block_len, block_cnt;
+       uint16_t out, in, head;
+       int err, err_cnt, i;
        uint8_t *status;
        void *block;
-       int err;
-       int err_cnt;
-
-       /* header */
-       desc_hdr                = virt_queue__pop(queue);
-
-       if (desc_hdr >= queue->vring.num) {
-               warning("fatal I/O error");
-               return false;
-       }
 
-       desc                    = virt_queue__get_desc(queue, desc_hdr);
-       assert(!(desc->flags & VRING_DESC_F_INDIRECT));
+       head                    = virt_queue__get_iov(queue, iov, &out, &in, self);
 
-       req                     = guest_flat_to_host(self, desc->addr);
-
-       /* status */
-       desc_status             = desc_hdr;
-
-       do {
-               desc_block_last = desc_status;
-               desc_status     = virt_queue__get_desc(queue, desc_status)->next;
-
-               if (desc_status >= queue->vring.num) {
-                       warning("fatal I/O error");
-                       return false;
-               }
-
-               desc            = virt_queue__get_desc(queue, desc_status);
-               assert(!(desc->flags & VRING_DESC_F_INDIRECT));
-
-       } while (desc->flags & VRING_DESC_F_NEXT);
-
-       status                  = guest_flat_to_host(self, desc->addr);
+       /* head */
+       req             = iov[0].iov_base;
 
        /* block */
-       desc_block              = desc_hdr;
-       block_cnt               = 0;
-       err_cnt                 = 0;
+       block_cnt       = 0;
+       err_cnt         = 0;
 
-       do {
-               desc_block      = virt_queue__get_desc(queue, desc_block)->next;
-
-               desc            = virt_queue__get_desc(queue, desc_block);
-               assert(!(desc->flags & VRING_DESC_F_INDIRECT));
-
-               block           = guest_flat_to_host(self, desc->addr);
-               block_len       = desc->len;
+       for (i = 1; i < out + in - 1; i++) {
+               block           = iov[i].iov_base;
+               block_len       = iov[i].iov_len;
 
                switch (req->type) {
                case VIRTIO_BLK_T_IN:
@@ -176,24 +139,28 @@ static bool virtio_blk_request(struct kvm *self, struct virt_queue *queue)
 
                req->sector     += block_len >> SECTOR_SHIFT;
                block_cnt       += block_len;
+       }
 
-               if (desc_block == desc_block_last)
-                       break;
-
-               if (desc_block >= queue->vring.num) {
-                       warning("fatal I/O error");
-                       return false;
-               }
-
-       } while (true);
-
+       /* status */
+       status                  = iov[out + in - 1].iov_base;
        *status                 = err_cnt ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
 
-       virt_queue__set_used_elem(queue, desc_hdr, block_cnt);
+       virt_queue__set_used_elem(queue, head, block_cnt);
 
        return true;
 }
 
+static void virtio_blk_handle_callback(struct kvm *self, uint16_t queue_index)
+{
+       struct virt_queue *vq;
+
+       vq = &blk_device.vqs[queue_index];
+       while (virt_queue__available(vq)) {
+               virtio_blk_do_io_request(self, vq);
+       }
+       kvm__irq_line(self, VIRTIO_BLK_IRQ, 1);
+
+}
 static bool virtio_blk_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
 {
        unsigned long offset;
@@ -208,7 +175,7 @@ static bool virtio_blk_pci_io_out(struct kvm *self, uint16_t port, void *data, i
                struct virt_queue *queue;
                void *p;
 
-               queue                   = &blk_device.virt_queues[blk_device.queue_selector];
+               queue                   = &blk_device.vqs[blk_device.queue_selector];
 
                queue->pfn              = ioport__read32(data);
 
@@ -222,19 +189,9 @@ static bool virtio_blk_pci_io_out(struct kvm *self, uint16_t port, void *data, i
                blk_device.queue_selector       = ioport__read16(data);
                break;
        case VIRTIO_PCI_QUEUE_NOTIFY: {
-               struct virt_queue *queue;
                uint16_t queue_index;
-
                queue_index             = ioport__read16(data);
-
-               queue                   = &blk_device.virt_queues[queue_index];
-
-               while (queue->vring.avail->idx != queue->last_avail_idx) {
-                       if (!virtio_blk_request(self, queue))
-                               return false;
-               }
-               kvm__irq_line(self, VIRTIO_BLK_IRQ, 1);
-
+               virtio_blk_handle_callback(self, queue_index);
                break;
        }
        case VIRTIO_PCI_STATUS: