diff options
author | Thomas Huth <thuth@redhat.com> | 2016-11-24 09:56:07 +0100 |
---|---|---|
committer | Alexey Kardashevskiy <aik@ozlabs.ru> | 2016-11-24 23:24:18 +1100 |
commit | 9290756ae1195b331373dbcfd3b37d978b3b71f4 (patch) | |
tree | 10cbafc1acf44c10c055ac275ce642b3fd24f650 /lib | |
parent | 9b8945ecbde65b06ea2ab9e28a6178024b0420fb (diff) | |
download | SLOF-9290756ae1195b331373dbcfd3b37d978b3b71f4.zip SLOF-9290756ae1195b331373dbcfd3b37d978b3b71f4.tar.gz SLOF-9290756ae1195b331373dbcfd3b37d978b3b71f4.tar.bz2 |
virtio-scsi: Fix descriptor order for SCSI WRITE commands
Virtio needs the descriptors ordered: All descriptors for buffers that
contain data that should go *to* the device have to be put into the
queue first. The descriptors for buffers that read *from* the device
have to be sorted in last. For SCSI WRITE commands (which we never
used in the past), the order was wrong, so QEMU complains with a
"Incorrect order for descriptors" message as soon as we use it for
SCSI WRITE commands.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libvirtio/virtio-scsi.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/lib/libvirtio/virtio-scsi.c b/lib/libvirtio/virtio-scsi.c index 04181b0..36b62d1 100644 --- a/lib/libvirtio/virtio-scsi.c +++ b/lib/libvirtio/virtio-scsi.c @@ -49,18 +49,27 @@ int virtioscsi_send(struct virtio_device *dev, virtio_fill_desc(&vq_desc[id], dev->is_modern, (uint64_t)req, sizeof(*req), VRING_DESC_F_NEXT, (id + 1) % vq_size); - /* Set up virtqueue descriptor for data */ - if (buf && buf_len) { + if (buf == NULL || buf_len == 0) { + /* Set up descriptor for response information */ + virtio_fill_desc(&vq_desc[(id + 1) % vq_size], dev->is_modern, + (uint64_t)resp, sizeof(*resp), + VRING_DESC_F_WRITE, 0); + } else if (is_read) { + /* Set up descriptor for response information */ virtio_fill_desc(&vq_desc[(id + 1) % vq_size], dev->is_modern, (uint64_t)resp, sizeof(*resp), VRING_DESC_F_NEXT | VRING_DESC_F_WRITE, (id + 2) % vq_size); - /* Set up virtqueue descriptor for status */ + /* Set up virtqueue descriptor for data from device */ virtio_fill_desc(&vq_desc[(id + 2) % vq_size], dev->is_modern, - (uint64_t)buf, buf_len, - (is_read ? VRING_DESC_F_WRITE : 0), 0); + (uint64_t)buf, buf_len, VRING_DESC_F_WRITE, 0); } else { + /* Set up virtqueue descriptor for data to device */ virtio_fill_desc(&vq_desc[(id + 1) % vq_size], dev->is_modern, + (uint64_t)buf, buf_len, VRING_DESC_F_NEXT, + (id + 2) % vq_size); + /* Set up descriptor for response information */ + virtio_fill_desc(&vq_desc[(id + 2) % vq_size], dev->is_modern, (uint64_t)resp, sizeof(*resp), VRING_DESC_F_WRITE, 0); } |