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>
This commit is contained in:
Rusty Russell 2015-02-13 17:13:42 +10:30
parent c97eb679ef
commit 3afe3e0f8d
1 changed files with 14 additions and 13 deletions

View 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");
max = desc[i].len / sizeof(struct vring_desc);
desc = check_pointer(desc[i].addr, desc[i].len);
i = 0;
}
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;
}
/* 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