aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio-blk.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2011-08-25 08:26:01 +0200
committerKevin Wolf <kwolf@redhat.com>2011-08-25 18:18:42 +0200
commita597e79ce14ea62266924acc7b8a7030a42ed29b (patch)
tree2dfae8672b7a3b85d3fa5e138c2ffe361e97cf29 /hw/virtio-blk.c
parent2f4b7593674e986e60b0b0f1a46707e0e149eb6d (diff)
downloadqemu-a597e79ce14ea62266924acc7b8a7030a42ed29b.zip
qemu-a597e79ce14ea62266924acc7b8a7030a42ed29b.tar.gz
qemu-a597e79ce14ea62266924acc7b8a7030a42ed29b.tar.bz2
block: explicit I/O accounting
Decouple the I/O accounting from bdrv_aio_readv/writev/flush and make the hardware models call directly into the accounting helpers. This means: - we do not count internal requests from image formats in addition to guest originating I/O - we do not double count I/O ops if the device model handles it chunk wise - we only account I/O once it actuall is done - can extent I/O accounting to synchronous or coroutine I/O easily - implement I/O latency tracking easily (see the next patch) I've conveted the existing device model callers to the new model, device models that are using synchronous I/O and weren't accounted before haven't been updated yet. Also scsi hasn't been converted to the end-to-end accounting as I want to defer that after the pending scsi layer overhaul. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw/virtio-blk.c')
-rw-r--r--hw/virtio-blk.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index dad8c0a..2a8ccd0 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -47,6 +47,7 @@ typedef struct VirtIOBlockReq
struct virtio_scsi_inhdr *scsi;
QEMUIOVector qiov;
struct VirtIOBlockReq *next;
+ BlockAcctCookie acct;
} VirtIOBlockReq;
static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
@@ -58,8 +59,6 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
stb_p(&req->in->status, status);
virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
virtio_notify(&s->vdev, s->vq);
-
- g_free(req);
}
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
@@ -81,6 +80,8 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
vm_stop(VMSTOP_DISKFULL);
} else {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ bdrv_acct_done(s->bs, &req->acct);
+ g_free(req);
bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
}
@@ -100,6 +101,8 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
}
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
+ bdrv_acct_done(req->dev->bs, &req->acct);
+ g_free(req);
}
static void virtio_blk_flush_complete(void *opaque, int ret)
@@ -113,6 +116,8 @@ static void virtio_blk_flush_complete(void *opaque, int ret)
}
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
+ bdrv_acct_done(req->dev->bs, &req->acct);
+ g_free(req);
}
static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
@@ -155,6 +160,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
*/
if (req->elem.out_num < 2 || req->elem.in_num < 3) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ g_free(req);
return;
}
@@ -163,6 +169,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
*/
if (req->elem.out_num > 2 && req->elem.in_num > 3) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
+ g_free(req);
return;
}
@@ -229,11 +236,13 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
stl_p(&req->scsi->data_len, hdr.dxfer_len);
virtio_blk_req_complete(req, status);
+ g_free(req);
}
#else
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
+ g_free(req);
}
#endif /* __linux__ */
@@ -266,6 +275,8 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
BlockDriverAIOCB *acb;
+ bdrv_acct_start(req->dev->bs, &req->acct, 0, BDRV_ACCT_FLUSH);
+
/*
* Make sure all outstanding writes are posted to the backing device.
*/
@@ -284,6 +295,8 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
sector = ldq_p(&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 (sector & req->dev->sector_mask) {
@@ -317,6 +330,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
sector = ldq_p(&req->out->sector);
+ bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
+
if (sector & req->dev->sector_mask) {
virtio_blk_rw_complete(req, -EIO);
return;
@@ -370,6 +385,7 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
s->serial ? s->serial : "",
MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
+ g_free(req);
} else if (type & VIRTIO_BLK_T_OUT) {
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
req->elem.out_num - 1);