From c71f14403f8f01086c62386784e421c9d45739a5 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 23 Nov 2010 10:31:46 -0200 Subject: [RHEL6 qemu-kvm PATCH 18/21] qcow2: Avoid bounce buffers for AIO write requests RH-Author: Kevin Wolf Message-id: <1290508306-11607-11-git-send-email-kwolf@redhat.com> Patchwork-id: 13834 O-Subject: [RHEL-6.1 qemu-kvm PATCH v2 10/10] qcow2: Avoid bounce buffers for AIO write requests Bugzilla: 653972 RH-Acked-by: Avi Kivity RH-Acked-by: Christoph Hellwig RH-Acked-by: Jes Sorensen Bugzilla: 653972 qcow2 used to use bounce buffers for any AIO requests. This does not only imply unnecessary copying, but also unbounded allocations which should be avoided. This patch removes bounce buffers from the normal AIO write path. Encrypted images continue to use a bounce buffer, however with constant size. Signed-off-by: Kevin Wolf (cherry picked from commit 6f5f060b736cedc2d962114d20805fdd2889513a) --- block/qcow2.c | 41 ++++++++++++++++++----------------------- 1 files changed, 18 insertions(+), 23 deletions(-) Signed-off-by: Eduardo Habkost --- block/qcow2.c | 41 ++++++++++++++++++----------------------- 1 files changed, 18 insertions(+), 23 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 780e282..57a6ee8 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -333,15 +333,12 @@ typedef struct QCowAIOCB { BlockDriverAIOCB common; int64_t sector_num; QEMUIOVector *qiov; - uint8_t *buf; - void *orig_buf; int remaining_sectors; int cur_nr_sectors; /* number of sectors in current iteration */ uint64_t bytes_done; uint64_t cluster_offset; uint8_t *cluster_data; BlockDriverAIOCB *hd_aiocb; - struct iovec hd_iov; QEMUIOVector hd_qiov; QEMUBH *bh; QCowL2Meta l2meta; @@ -532,14 +529,7 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, acb->sector_num = sector_num; acb->qiov = qiov; - if (!is_write) { - qemu_iovec_init(&acb->hd_qiov, qiov->niov); - } else if (qiov->niov == 1) { - acb->buf = (uint8_t *)qiov->iov->iov_base; - } else { - acb->buf = acb->orig_buf = qemu_blockalign(bs, qiov->size); - qemu_iovec_to_buffer(qiov, acb->buf); - } + qemu_iovec_init(&acb->hd_qiov, qiov->niov); acb->bytes_done = 0; acb->remaining_sectors = nb_sectors; @@ -597,7 +587,6 @@ static void qcow_aio_write_cb(void *opaque, int ret) BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; int index_in_cluster; - const uint8_t *src_buf; int n_end; acb->hd_aiocb = NULL; @@ -613,7 +602,7 @@ static void qcow_aio_write_cb(void *opaque, int ret) acb->remaining_sectors -= acb->cur_nr_sectors; acb->sector_num += acb->cur_nr_sectors; - acb->buf += acb->cur_nr_sectors * 512; + acb->bytes_done += acb->cur_nr_sectors * 512; if (acb->remaining_sectors == 0) { /* request completed */ @@ -644,20 +633,27 @@ static void qcow_aio_write_cb(void *opaque, int ret) assert((acb->cluster_offset & 511) == 0); + qemu_iovec_reset(&acb->hd_qiov); + qemu_iovec_copy(&acb->hd_qiov, acb->qiov, acb->bytes_done, + acb->cur_nr_sectors * 512); + if (s->crypt_method) { if (!acb->cluster_data) { acb->cluster_data = qemu_mallocz(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); } - qcow2_encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, - acb->cur_nr_sectors, 1, &s->aes_encrypt_key); - src_buf = acb->cluster_data; - } else { - src_buf = acb->buf; + + assert(acb->hd_qiov.size <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); + qemu_iovec_to_buffer(&acb->hd_qiov, acb->cluster_data); + + qcow2_encrypt_sectors(s, acb->sector_num, acb->cluster_data, + acb->cluster_data, acb->cur_nr_sectors, 1, &s->aes_encrypt_key); + + qemu_iovec_reset(&acb->hd_qiov); + qemu_iovec_add(&acb->hd_qiov, acb->cluster_data, + acb->cur_nr_sectors * 512); } - acb->hd_iov.iov_base = (void *)src_buf; - acb->hd_iov.iov_len = acb->cur_nr_sectors * 512; - qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); acb->hd_aiocb = bdrv_aio_writev(bs->file, (acb->cluster_offset >> 9) + index_in_cluster, @@ -675,9 +671,8 @@ fail: QLIST_REMOVE(&acb->l2meta, next_in_flight); } done: - if (acb->qiov->niov > 1) - qemu_vfree(acb->orig_buf); acb->common.cb(acb->common.opaque, ret); + qemu_iovec_destroy(&acb->hd_qiov); qemu_aio_release(acb); } -- 1.7.3.2