diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2014-03-12 20:53:40 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2014-03-12 20:57:57 -0400 |
commit | 70670444c20a10717acdc1f4c1e420852995496d (patch) | |
tree | e3204dac6bc05ab60836ae34695c948ea718be51 /drivers/virtio | |
parent | 9914a766174d50eb2343f204fef3ee23dbe07c4c (diff) |
virtio: fail adding buffer on broken queues.
Heinz points out that adding buffers to a broken virtqueue (which
should "never happen") still works. Failing allows drivers to detect
and complain about broken devices.
Now drivers are robust, we can add this extra check.
Reported-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/virtio')
-rw-r--r-- | drivers/virtio/virtio_ring.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 7ae3cba2f624..1e443629f76d 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -204,6 +204,11 @@ static inline int virtqueue_add(struct virtqueue *_vq, | |||
204 | 204 | ||
205 | BUG_ON(data == NULL); | 205 | BUG_ON(data == NULL); |
206 | 206 | ||
207 | if (unlikely(vq->broken)) { | ||
208 | END_USE(vq); | ||
209 | return -EIO; | ||
210 | } | ||
211 | |||
207 | #ifdef DEBUG | 212 | #ifdef DEBUG |
208 | { | 213 | { |
209 | ktime_t now = ktime_get(); | 214 | ktime_t now = ktime_get(); |
@@ -310,7 +315,7 @@ add_head: | |||
310 | * Caller must ensure we don't call this with other virtqueue operations | 315 | * Caller must ensure we don't call this with other virtqueue operations |
311 | * at the same time (except where noted). | 316 | * at the same time (except where noted). |
312 | * | 317 | * |
313 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM). | 318 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). |
314 | */ | 319 | */ |
315 | int virtqueue_add_sgs(struct virtqueue *_vq, | 320 | int virtqueue_add_sgs(struct virtqueue *_vq, |
316 | struct scatterlist *sgs[], | 321 | struct scatterlist *sgs[], |
@@ -348,7 +353,7 @@ EXPORT_SYMBOL_GPL(virtqueue_add_sgs); | |||
348 | * Caller must ensure we don't call this with other virtqueue operations | 353 | * Caller must ensure we don't call this with other virtqueue operations |
349 | * at the same time (except where noted). | 354 | * at the same time (except where noted). |
350 | * | 355 | * |
351 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM). | 356 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). |
352 | */ | 357 | */ |
353 | int virtqueue_add_outbuf(struct virtqueue *vq, | 358 | int virtqueue_add_outbuf(struct virtqueue *vq, |
354 | struct scatterlist sg[], unsigned int num, | 359 | struct scatterlist sg[], unsigned int num, |
@@ -370,7 +375,7 @@ EXPORT_SYMBOL_GPL(virtqueue_add_outbuf); | |||
370 | * Caller must ensure we don't call this with other virtqueue operations | 375 | * Caller must ensure we don't call this with other virtqueue operations |
371 | * at the same time (except where noted). | 376 | * at the same time (except where noted). |
372 | * | 377 | * |
373 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM). | 378 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). |
374 | */ | 379 | */ |
375 | int virtqueue_add_inbuf(struct virtqueue *vq, | 380 | int virtqueue_add_inbuf(struct virtqueue *vq, |
376 | struct scatterlist sg[], unsigned int num, | 381 | struct scatterlist sg[], unsigned int num, |