aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/virtio_blk.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2014-03-12 20:53:39 -0400
committerRusty Russell <rusty@rustcorp.com.au>2014-03-12 20:57:56 -0400
commit5261b85e586afe6ebe54e16e0a8acc32fc6d4902 (patch)
tree10ec38ad40d5e80e527b397c9f086d89d7175175 /drivers/block/virtio_blk.c
parenta7c58146cf9a782113629021ba5420582fef265e (diff)
virtio_blk: don't crash, report error if virtqueue is broken.
A bad implementation of virtio might cause us to mark the virtqueue broken: we'll dev_err() in that case, and the device is useless, but let's not BUG_ON(). ENOMEM or ENOSPC implies the ring is full, and we should try again later (-ENOMEM is documented to happen, but doesn't, as we fall through to ENOSPC). EIO means it's broken. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r--drivers/block/virtio_blk.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index b1cb3f4c4db4..a2db9ed288f2 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -158,6 +158,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
158 unsigned long flags; 158 unsigned long flags;
159 unsigned int num; 159 unsigned int num;
160 const bool last = (req->cmd_flags & REQ_END) != 0; 160 const bool last = (req->cmd_flags & REQ_END) != 0;
161 int err;
161 162
162 BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); 163 BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems);
163 164
@@ -198,11 +199,16 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
198 } 199 }
199 200
200 spin_lock_irqsave(&vblk->vq_lock, flags); 201 spin_lock_irqsave(&vblk->vq_lock, flags);
201 if (__virtblk_add_req(vblk->vq, vbr, vbr->sg, num) < 0) { 202 err = __virtblk_add_req(vblk->vq, vbr, vbr->sg, num);
203 if (err) {
202 virtqueue_kick(vblk->vq); 204 virtqueue_kick(vblk->vq);
203 spin_unlock_irqrestore(&vblk->vq_lock, flags); 205 spin_unlock_irqrestore(&vblk->vq_lock, flags);
204 blk_mq_stop_hw_queue(hctx); 206 blk_mq_stop_hw_queue(hctx);
205 return BLK_MQ_RQ_QUEUE_BUSY; 207 /* Out of mem doesn't actually happen, since we fall back
208 * to direct descriptors */
209 if (err == -ENOMEM || err == -ENOSPC)
210 return BLK_MQ_RQ_QUEUE_BUSY;
211 return BLK_MQ_RQ_QUEUE_ERROR;
206 } 212 }
207 213
208 if (last) 214 if (last)