Handle failed request processing with extra care:
 - If we got ENOMEM or EAGAIN, reverse vq head with
vhost_discard_vq_desc() and re-queue this callback. ENOMEM isn't
that critical, as we always allocate the memory with GFP_KERNEL
so it can reclaim or sleep anyway. But with EAGAIN we should
re-enter the function to properly check vq->backend.
 - On any other error, signal error and wait for next kick just
like vhost-net or vhost-scsi. After all, we can't do anything with
faulty guest request anyway.

https://virtuozzo.atlassian.net/browse/VSTOR-134034
Signed-off-by: Andrey Zhadchenko <[email protected]>
---

v2:
 - drop one missed vhost_discard_vq_desc(vq, 1);
 - change EGAIN and ENOMEM behaviour and expand commit message
with the reasoning

 drivers/vhost/blk.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/vhost/blk.c b/drivers/vhost/blk.c
index 7e33a4f30165d..6a1a2bab3bed8 100644
--- a/drivers/vhost/blk.c
+++ b/drivers/vhost/blk.c
@@ -540,7 +540,6 @@ static void vhost_blk_handle_guest_kick(struct vhost_work 
*work)
                ret = move_iovec(vq->iov, hdr_iovec, sizeof(hdr), in + out, 
ARRAY_SIZE(hdr_iovec));
                if (ret < 0) {
                        vhostblk_vq_err(blk, vq, "virtio_blk_hdr (head %d) is 
too split!", head);
-                       vhost_discard_vq_desc(vq, 1);
                        break;
                }
 
@@ -549,12 +548,17 @@ static void vhost_blk_handle_guest_kick(struct vhost_work 
*work)
                if (ret != sizeof(hdr)) {
                        vhostblk_vq_err(blk, vq, "Failed to get read header 
(head %d): got %d, expected %ld!\n",
                                        head, ret, sizeof(hdr));
-                       vhost_discard_vq_desc(vq, 1);
                        break;
                }
 
-               if (vhost_blk_req_handle(vq, &hdr, head, out + in) < 0) {
+               ret = vhost_blk_req_handle(vq, &hdr, head, out + in);
+               if (ret == -EAGAIN || ret == -ENOMEM) {
                        vhost_discard_vq_desc(vq, 1);
+                       vhost_poll_queue(&vq->poll);
+                       break;
+               } else if (ret < 0) {
+                       vhostblk_vq_err(blk, vq, "Failed to process guest 
request (head %d) with %d",
+                                       head, ret);
                        break;
                }
 
-- 
2.43.5

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to