Skip to contentSkip to conversation

Fix whitespace in virtio

PATCH In review Anthony Liguori 3 participants 11 messages Dec 3, 2008 – Dec 14, 2008 KVM

lore
Share & tools
lore
#0 lore raw

PATCH 1/7 Fix whitespace in virtio

Whoever originally wrote the virtio code quite rudely didn't configure their editor to use spaces instead of tabs. This patch corrects this for all virtio related files.

qemu/hw/virtio-balloon.c +22 -22
index 111f27d..9b34e87 100644
@@ -79,26 +79,26 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
     VirtQueueElement elem;
 
     while (virtqueue_pop(vq, &elem)) {
-	size_t offset = 0;
-	uint32_t pfn;
+        size_t offset = 0;
+        uint32_t pfn;
 
-	while (memcpy_from_iovector(&pfn, offset, 4,
+        while (memcpy_from_iovector(&pfn, offset, 4,
                                     elem.out_sg, elem.out_num) == 4) {
-	    ram_addr_t pa;
-	    ram_addr_t addr;
+            ram_addr_t pa;
+            ram_addr_t addr;
 
-	    pa = (ram_addr_t)ldl_p(&pfn) << VIRTIO_BALLOON_PFN_SHIFT;
-	    offset += 4;
+            pa = (ram_addr_t)ldl_p(&pfn) << VIRTIO_BALLOON_PFN_SHIFT;
+            offset += 4;
 
-	    addr = cpu_get_physical_page_desc(pa);
-	    if ((addr & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
-		continue;
+            addr = cpu_get_physical_page_desc(pa);
+            if ((addr & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+                continue;
 
-	    balloon_page(phys_ram_base + addr, !!(vq == s->dvq));
-	}
+            balloon_page(phys_ram_base + addr, !!(vq == s->dvq));
+        }
 
-	virtqueue_push(vq, &elem, offset);
-	virtio_notify(vdev, vq);
+        virtqueue_push(vq, &elem, offset);
+        virtio_notify(vdev, vq);
     }
 }
 
@@ -114,7 +114,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
 }
 
 static void virtio_balloon_set_config(VirtIODevice *vdev,
-				      const uint8_t *config_data)
+                                      const uint8_t *config_data)
 {
     VirtIOBalloon *dev = to_virtio_balloon(vdev);
     struct virtio_balloon_config config;
@@ -132,11 +132,11 @@ static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target)
     VirtIOBalloon *dev = opaque;
 
     if (target > ram_size)
-	target = ram_size;
+        target = ram_size;
 
     if (target) {
-	dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
-	virtio_notify_config(&dev->vdev);
+        dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
+        virtio_notify_config(&dev->vdev);
     }
 
     return ram_size - (dev->actual << VIRTIO_BALLOON_PFN_SHIFT);
@@ -172,10 +172,10 @@ void *virtio_balloon_init(PCIBus *bus)
     VirtIOBalloon *s;
 
     s = (VirtIOBalloon *)virtio_init_pci(bus, "virtio-balloon",
-					 6900, 0x1002,
-					 0, VIRTIO_ID_BALLOON,
-					 0x05, 0x00, 0x00,
-					 8, sizeof(VirtIOBalloon));
+                                         6900, 0x1002,
+                                         0, VIRTIO_ID_BALLOON,
+                                         0x05, 0x00, 0x00,
+                                         8, sizeof(VirtIOBalloon));
     if (s == NULL)
         return NULL;
 
qemu/hw/virtio-balloon.h +2 -2
index 0466a48..45e4b03 100644
@@ -18,10 +18,10 @@
 /* from Linux's linux/virtio_balloon.h */
 
 /* The ID for virtio_balloon */
-#define VIRTIO_ID_BALLOON	5
+#define VIRTIO_ID_BALLOON 5
 
 /* The feature bitmap for virtio balloon */
-#define VIRTIO_BALLOON_F_MUST_TELL_HOST	0 /* Tell before reclaiming pages */
+#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */
 
 /* Size of a PFN in the balloon interface. */
 #define VIRTIO_BALLOON_PFN_SHIFT 12
qemu/hw/virtio-blk.c +104 -104

281 lines not on this page · raw message

qemu/hw/virtio-net.c +140 -140

398 lines not on this page · raw message

qemu/hw/virtio.c +172 -172

576 lines not on this page · raw message

qemu/hw/virtio.h +18 -18
index 15f020b..40c9e14 100644
@@ -22,13 +22,13 @@
 
 /* Status byte for guest to report progress, and synchronize features. */
 /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
-#define VIRTIO_CONFIG_S_ACKNOWLEDGE	1
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
 /* We have found a driver for the device. */
-#define VIRTIO_CONFIG_S_DRIVER		2
+#define VIRTIO_CONFIG_S_DRIVER          2
 /* Driver has used its parts of the config, and is happy */
-#define VIRTIO_CONFIG_S_DRIVER_OK	4
+#define VIRTIO_CONFIG_S_DRIVER_OK       4
 /* We've given up on this device. */
-#define VIRTIO_CONFIG_S_FAILED		0x80
+#define VIRTIO_CONFIG_S_FAILED          0x80
 
 /* We notify when the ring is completely used, even if the guest is supressing
  * callbacks */
@@ -37,14 +37,14 @@
 /* from Linux's linux/virtio_ring.h */
 
 /* This marks a buffer as continuing via the next field. */
-#define VRING_DESC_F_NEXT	1
+#define VRING_DESC_F_NEXT       1
 /* This marks a buffer as write-only (otherwise read-only). */
-#define VRING_DESC_F_WRITE	2
+#define VRING_DESC_F_WRITE      2
 
 /* This means don't notify other side when buffer added. */
-#define VRING_USED_F_NO_NOTIFY	1
+#define VRING_USED_F_NO_NOTIFY  1
 /* This means don't interrupt guest when buffer consumed. */
-#define VRING_AVAIL_F_NO_INTERRUPT	1
+#define VRING_AVAIL_F_NO_INTERRUPT      1
 
 typedef struct VirtQueue VirtQueue;
 typedef struct VirtIODevice VirtIODevice;
@@ -105,7 +105,7 @@ typedef struct VirtQueueElement
     struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
 } VirtQueueElement;
 
-#define VIRTIO_PCI_QUEUE_MAX	16
+#define VIRTIO_PCI_QUEUE_MAX 16
 
 struct VirtIODevice
 {
@@ -127,21 +127,21 @@ struct VirtIODevice
 };
 
 VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
-			      uint16_t vendor, uint16_t device,
-			      uint16_t subvendor, uint16_t subdevice,
-			      uint8_t class_code, uint8_t subclass_code,
-			      uint8_t pif, size_t config_size,
-			      size_t struct_size);
+                              uint16_t vendor, uint16_t device,
+                              uint16_t subvendor, uint16_t subdevice,
+                              uint8_t class_code, uint8_t subclass_code,
+                              uint8_t pif, size_t config_size,
+                              size_t struct_size);
 
 VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
-			    void (*handle_output)(VirtIODevice *,
-						  VirtQueue *));
+                            void (*handle_output)(VirtIODevice *,
+                                                  VirtQueue *));
 
 void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
-		    unsigned int len);
+                    unsigned int len);
 void virtqueue_flush(VirtQueue *vq, unsigned int count);
 void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
-		    unsigned int len, unsigned int idx);
+                    unsigned int len, unsigned int idx);
 
 int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);
 int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes);
#1 lore raw

PATCH 2/7 Create virtio-blk.h header

Besides cleanliness, targets other than pc want to use virtio-blk so we need to have to define it somewhere other than pc.h

qemu/hw/pc.c +1 -0
index 6de460c..ee38326 100644
@@ -34,6 +34,7 @@
 #include "console.h"
 #include "fw_cfg.h"
 #include "device-assignment.h"
+#include "virtio-blk.h"
 
 #include "qemu-kvm.h"
 
qemu/hw/pc.h +0 -4
index 5349a41..a874fbd 100644
@@ -168,10 +168,6 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
 
 PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
 
-/* virtio-blk.h */
-void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device,
-		      BlockDriverState *bs);
-
 /* extboot.c */
 
 void extboot_init(BlockDriverState *bs, int cmd);
qemu/hw/virtio-blk.c +1 -55

63 lines not on this page · raw message

qemu/hw/virtio-blk.h new file +76 -0

76 lines not on this page · raw message

#2 lore raw

PATCH 3/7 Create virtio-net.h header

Besides cleanliness, targets other than pc want to use virtio-net so we need to have to define it somewhere other than pc.h

qemu/hw/pc.h +0 -4
index a874fbd..5b90198 100644
@@ -164,10 +164,6 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
 
 void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
 
-/* virtio-net.c */
-
-PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
-
 /* extboot.c */
 
 void extboot_init(BlockDriverState *bs, int cmd);
qemu/hw/pci.c +1 -0
index 75bc9a9..c93758d 100644
@@ -27,6 +27,7 @@
 #include "net.h"
 #include "pc.h"
 #include "qemu-kvm.h"
+#include "virtio-net.h"
 
 //#define DEBUG_PCI
 
qemu/hw/virtio-net.c +1 -57

66 lines not on this page · raw message

qemu/hw/virtio-net.h new file +80 -0

80 lines not on this page · raw message

#3 lore raw

PATCH 4/7 Move virtio_balloon_init to virtio-balloon.h

Besides cleanliness, targets other than pc want to use virtio-balloon so we need to have to define it somewhere other than pc.h

qemu/hw/pc.c +1 -0
index ee38326..92a8615 100644
@@ -35,6 +35,7 @@
 #include "fw_cfg.h"
 #include "device-assignment.h"
 #include "virtio-blk.h"
+#include "virtio-balloon.h"
 
 #include "qemu-kvm.h"
 
qemu/hw/pc.h +0 -3
index 5b90198..8cfa1ca 100644
@@ -168,7 +168,4 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
 
 void extboot_init(BlockDriverState *bs, int cmd);
 
-/* virtio-balloon.h */
-void *virtio_balloon_init(PCIBus *bus);
-
 #endif
qemu/hw/virtio-balloon.h +5 -0
index 45e4b03..c71f970 100644
@@ -15,6 +15,9 @@
 #ifndef _QEMU_VIRTIO_BALLOON_H
 #define _QEMU_VIRTIO_BALLOON_H
 
+#include "virtio.h"
+#include "pci.h"
+
 /* from Linux's linux/virtio_balloon.h */
 
 /* The ID for virtio_balloon */
@@ -34,4 +37,6 @@ struct virtio_balloon_config
     uint32_t actual;
 };
 
+void *virtio_balloon_init(PCIBus *bus);
+
 #endif
#4 lore raw

PATCH 5/7 Do not access virtio-rings directly

This introduces accessors for all virtio ring members and then uses the appropriate physical memory accessors. We shouldn't access guest physical memory directly and this fixes that. As a consequence, this helps us get closer to working live migration.

I've done light performance testing and it seems to not have an impact. If further testing demonstrates an impact, we can optimize the physical memory accessor functions.

qemu/hw/virtio-net.c +7 -7
index f621ff3..b64fb00 100644
@@ -101,18 +101,18 @@ static int virtio_net_can_receive(void *opaque)
 {
     VirtIONet *n = opaque;
 
-    if (n->rx_vq->vring.avail == NULL ||
+    if (!virtio_queue_ready(n->rx_vq) ||
         !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
         return 0;
 
-    if (n->rx_vq->vring.avail->idx == n->rx_vq->last_avail_idx ||
+    if (virtio_queue_empty(n->rx_vq) ||
         (n->mergeable_rx_bufs &&
          !virtqueue_avail_bytes(n->rx_vq, VIRTIO_NET_MAX_BUFSIZE, 0))) {
-        n->rx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+        virtio_queue_set_notification(n->rx_vq, 1);
         return 0;
     }
 
-    n->rx_vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+    virtio_queue_set_notification(n->rx_vq, 0);
     return 1;
 }
 
@@ -295,7 +295,7 @@ static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
     VirtIONet *n = to_virtio_net(vdev);
 
     if (n->tx_timer_active) {
-        vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+        virtio_queue_set_notification(vq, 1);
         qemu_del_timer(n->tx_timer);
         n->tx_timer_active = 0;
         virtio_net_flush_tx(n, vq);
@@ -303,7 +303,7 @@ static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
         qemu_mod_timer(n->tx_timer,
                        qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
         n->tx_timer_active = 1;
-        vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+        virtio_queue_set_notification(vq, 0);
     }
 }
 
@@ -317,7 +317,7 @@ static void virtio_net_tx_timer(void *opaque)
     if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
         return;
 
-    n->tx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+    virtio_queue_set_notification(n->tx_vq, 1);
     virtio_net_flush_tx(n, n->tx_vq);
 }
 
qemu/hw/virtio.c +180 -39

328 lines not on this page · raw message

qemu/hw/virtio.h +9 -46

74 lines not on this page · raw message

#5 lore raw

PATCH 6/7 Do not modify VirtQueueElement

Right now, virtio-net modifies the iovec structure in VirtQueueElement. This is evil. This creates an impossible situation if we want to bounce iovec buffers in VirtQueueElement as we lose track of the original buffers and the resulting free results in very bad things.

I tried to refactor receive_headers() and iov_fill() to be able to skip the header if present but failed miserably. Instead of spending more time trying to get that to work, I simply decided to leave the code as-is and copy the iovec to a temporary buffer.

I doubt there will be any performance impact as usually there are only a few elements in the iovec anyway.

qemu/hw/virtio-net.c +6 -3
index b64fb00..6493ff6 100644
@@ -198,6 +198,7 @@ static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
     while (offset < size) {
         VirtQueueElement elem;
         int len, total;
+        struct iovec sg[VIRTQUEUE_MAX_SIZE];
 
         len = total = 0;
 
@@ -219,17 +220,19 @@ static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
             exit(1);
         }
 
+        memcpy(&sg, &elem.in_sg[0], sizeof(sg[0]) * elem.in_num);
+
         if (i == 0) {
             if (n->mergeable_rx_bufs)
-                mhdr = (struct virtio_net_hdr_mrg_rxbuf *)elem.in_sg[0].iov_base;
+                mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
 
-            offset += receive_header(n, &elem.in_sg[0], elem.in_num,
+            offset += receive_header(n, sg, elem.in_num,
                                      buf + offset, size - offset, hdr_len);
             total += hdr_len;
         }
 
         /* copy in packet.  ugh */
-        len = iov_fill(&elem.in_sg[0], elem.in_num,
+        len = iov_fill(sg, elem.in_num,
                        buf + offset, size - offset);
         total += len;
 
#6 lore raw

PATCH 7/7 Optionally bounce the virtio buffers

In the absence of a zero-copy API, we cannot touch physical memory directly. This patch introduces a #define to control whether we touch buffers directly, or bounce the buffers through cpu_physical_memory_rw.

The #define is needed for merging virtio into upstream QEMU since zero-copy will not be accepted as-is. As a bonus, I also added physical memory dirtying support to the zero-copy case so now live migration should work when using virtio.

With this patch, virtio is mergable into upstream QEMU (except for virtio-net, that's a different series though).

qemu/hw/virtio.c +59 -2
index 1a58940..9396580 100644
@@ -17,6 +17,8 @@
 #include "virtio.h"
 #include "sysemu.h"
 
+//#define VIRTIO_ZERO_COPY
+
 /* from Linux's linux/virtio_pci.h */
 
 /* A 32-bit r/o bitmask of the features supported by the host */
@@ -104,6 +106,7 @@ struct VirtQueue
 #define VIRTIO_PCI_QUEUE_MAX        16
 
 /* virt queue functions */
+#ifdef VIRTIO_ZERO_COPY
 static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
 {
     ram_addr_t off;
@@ -138,6 +141,7 @@ static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
 
     return phys_ram_base + off;
 }
+#endif
 
 static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa)
 {
@@ -258,6 +262,38 @@ int virtio_queue_empty(VirtQueue *vq)
 void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                     unsigned int len, unsigned int idx)
 {
+    unsigned int offset;
+    int i;
+
+#ifndef VIRTIO_ZERO_COPY
+    for (i = 0; i < elem->out_num; i++)
+        qemu_free(elem->out_sg[i].iov_base);
+#endif
+
+    offset = 0;
+    for (i = 0; i < elem->in_num; i++) {
+        size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
+
+#ifdef VIRTIO_ZERO_COPY
+        if (size) {
+            ram_addr_t addr = (uint8_t *)elem->in_sg[i].iov_base - phys_ram_base;
+            ram_addr_t off;
+
+            for (off = 0; off < size; off += TARGET_PAGE_SIZE)
+                cpu_physical_memory_set_dirty(addr + off);
+        }
+#else
+        if (size)
+            cpu_physical_memory_write(elem->in_addr[i],
+                                      elem->in_sg[i].iov_base,
+                                      size);
+
+        qemu_free(elem->in_sg[i].iov_base);
+#endif
+        
+        offset += size;
+    }
+
     idx = (idx + vring_used_idx(vq)) % vq->vring.num;
 
     /* Get a pointer to the next entry in the used ring. */
@@ -372,14 +408,35 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
     do {
         struct iovec *sg;
 
-        if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE)
+        if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
+            elem->in_addr[elem->in_num] = vring_desc_addr(vq, i);
             sg = &elem->in_sg[elem->in_num++];
-        else
+        } else
             sg = &elem->out_sg[elem->out_num++];
 
         /* Grab the first descriptor, and check it's OK. */
         sg->iov_len = vring_desc_len(vq, i);
+
+#ifdef VIRTIO_ZERO_COPY
         sg->iov_base = virtio_map_gpa(vring_desc_addr(vq, i), sg->iov_len);
+#else
+        /* cap individual scatter element size to prevent unbounded allocations
+           of memory from the guest.  Practically speaking, no virtio driver
+           will ever pass more than a page in each element.  We set the cap to
+           be 2MB in case for some reason a large page makes it way into the
+           sg list.  When we implement a zero copy API, this limitation will
+           disappear */
+        if (sg->iov_len > (2 << 20))
+            sg->iov_len = 2 << 20;
+
+        sg->iov_base = qemu_malloc(sg->iov_len);
+        if (sg->iov_base && 
+            !(vring_desc_flags(vq, i) & VRING_DESC_F_WRITE)) {
+            cpu_physical_memory_read(vring_desc_addr(vq, i),
+                                     sg->iov_base,
+                                     sg->iov_len);
+        }
+#endif
         if (sg->iov_base == NULL)
             errx(1, "Invalid mapping\n");
 
qemu/hw/virtio.h +1 -0
index 86dc36a..f04e75f 100644
@@ -58,6 +58,7 @@ typedef struct VirtQueueElement
     unsigned int index;
     unsigned int out_num;
     unsigned int in_num;
+    target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE];
     struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
     struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
 } VirtQueueElement;
#7 lore raw

PATCH 1/1 kvm: qemu: virtio: enable VIRTIO_ZERO_COPY

Quoted 19 lines · Anthony Liguori

In the absence of a zero-copy API, we cannot touch physical memory directly. This patch introduces a #define to control whether we touch buffers directly, or bounce the buffers through cpu_physical_memory_rw.

The #define is needed for merging virtio into upstream QEMU since zero-copy will not be accepted as-is. As a bonus, I also added physical memory dirtying support to the zero-copy case so now live migration should work when using virtio.

With this patch, virtio is mergable into upstream QEMU (except for virtio-net, that's a different series though).

qemu/hw/virtio.c +0 -0
index 1a58940..9396580 100644

qemu/hw/virtio.c line 21

Quoted 5 lines
qemu/hw/virtio.c +2 -0
@@ -17,6 +17,8 @@
 #include "virtio.h"
 #include "sysemu.h"
 
+//#define VIRTIO_ZERO_COPY
+

From: Mark McLoughlin <[email protected]>
Subject: [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY

Anthony intended to enable VIRTIO_ZERO_COPY before submitting, so do that now.

Fixes an oops in the bounce buffer malloc in virtqueue_pop() I have seen twice so far. We still need to track this down, but it's very hard to reproduce.

---
 qemu/hw/virtio.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
qemu/hw/virtio.c +1 -1
index 16356e8..1d06fcc 100644
@@ -16,7 +16,7 @@
 #include "virtio.h"
 #include "sysemu.h"
 
-//#define VIRTIO_ZERO_COPY
+#define VIRTIO_ZERO_COPY
 
 /* from Linux's linux/virtio_pci.h */
 
Signature · 1 line
1.5.4.3
Applied
#8 lore raw

Re: [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY

Quoted 8 lines · Mark McLoughlin

Anthony intended to enable VIRTIO_ZERO_COPY before submitting, so do that now.

Fixes an oops in the bounce buffer malloc in virtqueue_pop() I have seen twice so far. We still need to track this down, but it's very hard to reproduce.

Applied, thanks.

Signature · 1 line
error compiling committee.c: too many arguments to function
#9 lore raw

Re: [PATCH 6/7] Do not modify VirtQueueElement

In reply to Anthony Liguori
Quoted 9 lines · Anthony Liguori

Right now, virtio-net modifies the iovec structure in VirtQueueElement. This is evil. This creates an impossible situation if we want to bounce iovec buffers in VirtQueueElement as we lose track of the original buffers and the resulting free results in very bad things.

I tried to refactor receive_headers() and iov_fill() to be able to skip the header if present but failed miserably. Instead of spending more time trying to get that to work, I simply decided to leave the code as-is and copy the iovec to a temporary buffer.

Sounds sensible to me.

We could perhaps make things a bit more clear by never using the guest supplied header and always translating between the two header formats.

But whatever way we do it, if we want to avoid modifying the original iovec structure, we need the temporary buffer.

Cheers,
Mark.

#10 lore raw
In reply to Anthony Liguori
Quoted 5 lines · Anthony Liguori

Whoever originally wrote the virtio code quite rudely didn't configure their editor to use spaces instead of tabs. This patch corrects this for all virtio related files.

Applied all seven. Note the last patch added trailing whitespace, which I removed, so this can cause a difference wrt qemu.

Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.