diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/virtio_blk.c | 10 |
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) |