958e1b
From 8406a85d6b78d2f3478a204b5eab0cd714fe9aa4 Mon Sep 17 00:00:00 2001
958e1b
From: Markus Armbruster <armbru@redhat.com>
958e1b
Date: Fri, 31 Oct 2014 16:29:53 +0100
958e1b
Subject: [PATCH 16/19] virtio-blk: Bypass error action and I/O accounting on
958e1b
 invalid r/w
958e1b
958e1b
Message-id: <1414772996-17272-3-git-send-email-armbru@redhat.com>
958e1b
Patchwork-id: 62014
958e1b
O-Subject: [PATCH RHEL-7.1 qemu-kvm 2/5] virtio-blk: Bypass error action and I/O accounting on invalid r/w
958e1b
Bugzilla: 1085232
958e1b
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
958e1b
RH-Acked-by: Fam Zheng <famz@redhat.com>
958e1b
958e1b
When a device model's I/O operation fails, we execute the error
958e1b
action.  This lets layers above QEMU implement thin provisioning, or
958e1b
attempt to correct errors before they reach the guest.  But when the
958e1b
I/O operation fails because it's invalid, reporting the error to the
958e1b
guest is the only sensible action.
958e1b
958e1b
If the guest's read or write asks for an invalid sector range, fail
958e1b
the request right away, without considering the error action.  No
958e1b
change with error action BDRV_ACTION_REPORT.
958e1b
958e1b
Furthermore, bypass I/O accounting, because we want to track only I/O
958e1b
that actually reaches the block layer.
958e1b
958e1b
The next commit will extend "invalid sector range" to cover attempts
958e1b
to read/write beyond the end of the medium.
958e1b
958e1b
Signed-off-by: Markus Armbruster <armbru@redhat.com>
958e1b
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
958e1b
(cherry picked from commit 42e38c1fd0199155d32f3464aedce282d3d7f6a1)
958e1b
958e1b
Straightforward semantic conflict: requests still have to be freed
958e1b
with g_free() because we don't have commit 671ec3f.
958e1b
958e1b
Signed-off-by: Markus Armbruster <armbru@redhat.com>
958e1b
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
958e1b
---
958e1b
 hw/block/virtio-blk.c | 14 ++++++++------
958e1b
 1 file changed, 8 insertions(+), 6 deletions(-)
958e1b
958e1b
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
958e1b
index 0f1d3ec..ffb311c 100644
958e1b
--- a/hw/block/virtio-blk.c
958e1b
+++ b/hw/block/virtio-blk.c
958e1b
@@ -300,15 +300,16 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
958e1b
 
958e1b
     sector = ldq_p(&req->out->sector);
958e1b
 
958e1b
-    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
958e1b
-
958e1b
     trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
958e1b
 
958e1b
     if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
958e1b
-        virtio_blk_rw_complete(req, -EIO);
958e1b
+        virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
958e1b
+        g_free(req);
958e1b
         return;
958e1b
     }
958e1b
 
958e1b
+    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
958e1b
+
958e1b
     if (mrb->num_writes == 32) {
958e1b
         virtio_submit_multiwrite(req->dev->bs, mrb);
958e1b
     }
958e1b
@@ -330,14 +331,15 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
958e1b
 
958e1b
     sector = ldq_p(&req->out->sector);
958e1b
 
958e1b
-    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
958e1b
-
958e1b
     trace_virtio_blk_handle_read(req, sector, req->qiov.size / 512);
958e1b
 
958e1b
     if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
958e1b
-        virtio_blk_rw_complete(req, -EIO);
958e1b
+        virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
958e1b
+        g_free(req);
958e1b
         return;
958e1b
     }
958e1b
+
958e1b
+    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
958e1b
     bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
958e1b
                    req->qiov.size / BDRV_SECTOR_SIZE,
958e1b
                    virtio_blk_rw_complete, req);
958e1b
-- 
958e1b
1.8.3.1
958e1b