tools/lguest: handle indirect partway through chain.
authorRusty Russell <rusty@rustcorp.com.au>
Fri, 13 Feb 2015 06:43:42 +0000 (17:13 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 13 Feb 2015 06:45:50 +0000 (17:15 +1030)
Linux doesn't generate these, but it's perfectly valid according to
a close reading of the spec.  I opened virtio spec bug VIRTIO-134 to
make this clearer there, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
tools/lguest/lguest.c

index 80dc634..990671e 100644 (file)
@@ -769,20 +769,21 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
         * that: no rmb() required.
         */
 
-       /*
-        * If this is an indirect entry, then this buffer contains a descriptor
-        * table which we handle as if it's any normal descriptor chain.
-        */
-       if (desc[i].flags & VRING_DESC_F_INDIRECT) {
-               if (desc[i].len % sizeof(struct vring_desc))
-                       errx(1, "Invalid size for indirect buffer table");
+       do {
+               /*
+                * If this is an indirect entry, then this buffer contains a
+                * descriptor table which we handle as if it's any normal
+                * descriptor chain.
+                */
+               if (desc[i].flags & VRING_DESC_F_INDIRECT) {
+                       if (desc[i].len % sizeof(struct vring_desc))
+                               errx(1, "Invalid size for indirect buffer table");
 
-               max = desc[i].len / sizeof(struct vring_desc);
-               desc = check_pointer(desc[i].addr, desc[i].len);
-               i = 0;
-       }
+                       max = desc[i].len / sizeof(struct vring_desc);
+                       desc = check_pointer(desc[i].addr, desc[i].len);
+                       i = 0;
+               }
 
-       do {
                /* Grab the first descriptor, and check it's OK. */
                iov[*out_num + *in_num].iov_len = desc[i].len;
                iov[*out_num + *in_num].iov_base