summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2015-02-13 17:13:42 +1030
committerRusty Russell <rusty@rustcorp.com.au>2015-02-13 17:15:50 +1030
commit3afe3e0f8db10a41a5923e1d7498318877473f33 (patch)
tree4da04fb2dde7e05c298e8a481c6cc5d6eb096c69
parentc97eb679ef70dbb4482e66b9d192fc9e5bc6e0d6 (diff)
tools/lguest: handle indirect partway through chain.
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>
-rw-r--r--tools/lguest/lguest.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index 80dc6346030e..990671e61f87 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -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