aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2014-07-09 19:07:30 +0200
committerKevin Wolf <kwolf@redhat.com>2014-07-14 12:03:21 +0200
commit42e38c1fd0199155d32f3464aedce282d3d7f6a1 (patch)
treeee831dcb6b0876eb0e0c04b68c2d70d7e08ab932 /hw
parentd0e14376eefc40b07c8fb42c132c2202c66dcb0b (diff)
virtio-blk: Bypass error action and I/O accounting on invalid r/w
When a device model's I/O operation fails, we execute the error action. This lets layers above QEMU implement thin provisioning, or attempt to correct errors before they reach the guest. But when the I/O operation fails because it's invalid, reporting the error to the guest is the only sensible action. If the guest's read or write asks for an invalid sector range, fail the request right away, without considering the error action. No change with error action BDRV_ACTION_REPORT. Furthermore, bypass I/O accounting, because we want to track only I/O that actually reaches the block layer. The next commit will extend "invalid sector range" to cover attempts to read/write beyond the end of the medium. Signed-off-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/block/virtio-blk.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 075e6e626f..e6e62768e4 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -307,15 +307,16 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);
- bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
-
trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
- virtio_blk_rw_complete(req, -EIO);
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ virtio_blk_free_request(req);
return;
}
+ bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
+
if (mrb->num_writes == 32) {
virtio_submit_multiwrite(req->dev->bs, mrb);
}
@@ -337,14 +338,15 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);
- bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
-
trace_virtio_blk_handle_read(req, sector, req->qiov.size / 512);
if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
- virtio_blk_rw_complete(req, -EIO);
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ virtio_blk_free_request(req);
return;
}
+
+ bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
req->qiov.size / BDRV_SECTOR_SIZE,
virtio_blk_rw_complete, req);