Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+8 -2
+8 -2
drivers/block/virtio_blk.c
··· 158 158 unsigned long flags; 159 159 unsigned int num; 160 160 const bool last = (req->cmd_flags & REQ_END) != 0; 161 + int err; 161 162 162 163 BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); 163 164 ··· 199 198 } 200 199 201 200 spin_lock_irqsave(&vblk->vq_lock, flags); 202 - if (__virtblk_add_req(vblk->vq, vbr, vbr->sg, num) < 0) { 201 + err = __virtblk_add_req(vblk->vq, vbr, vbr->sg, num); 202 + if (err) { 203 203 virtqueue_kick(vblk->vq); 204 204 spin_unlock_irqrestore(&vblk->vq_lock, flags); 205 205 blk_mq_stop_hw_queue(hctx); 206 - return BLK_MQ_RQ_QUEUE_BUSY; 206 + /* Out of mem doesn't actually happen, since we fall back 207 + * to direct descriptors */ 208 + if (err == -ENOMEM || err == -ENOSPC) 209 + return BLK_MQ_RQ_QUEUE_BUSY; 210 + return BLK_MQ_RQ_QUEUE_ERROR; 207 211 } 208 212 209 213 if (last)