diff mbox

virtio-scsi: Fix descriptor order for SCSI WRITE commands

Message ID 1479977767-14027-1-git-send-email-thuth@redhat.com
State Accepted
Headers show

Commit Message

Thomas Huth Nov. 24, 2016, 8:56 a.m. UTC
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>
---
 lib/libvirtio/virtio-scsi.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

Comments

Alexey Kardashevskiy Dec. 1, 2016, 2:28 a.m. UTC | #1
On 24/11/16 19:56, Thomas Huth wrote:
> 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>

Thanks, applied.

> ---
>  lib/libvirtio/virtio-scsi.c | 19 ++++++++++++++-----
>  1 file 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);
>  	}
>
diff mbox

Patch

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);
 	}