This really makes my life much easier! Signed-off-by: Asias He <asias.hejun@xxxxxxxxx> --- tools/kvm/virtio-blk.c | 109 ++++++++++++++--------------------------------- 1 files changed, 33 insertions(+), 76 deletions(-) diff --git a/tools/kvm/virtio-blk.c b/tools/kvm/virtio-blk.c index 8351e7a..34eb3f7 100644 --- a/tools/kvm/virtio-blk.c +++ b/tools/kvm/virtio-blk.c @@ -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: -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html