From 0354b9a036d653d8af5b38211a80dddff95310e5 Mon Sep 17 00:00:00 2001 From: Jeffrey Cody Date: Wed, 21 Mar 2012 21:54:28 +0100 Subject: [PATCH 01/55] Revert "qed: intelligent streaming implementation" RH-Author: Jeffrey Cody Message-id: <1bbfd99be251702dbd78f9d7391f548f0a667c58.1332362400.git.jcody@redhat.com> Patchwork-id: 38851 O-Subject: [RHEL6.3 qemu-kvm PATCH v8 01/54] Revert "qed: intelligent streaming implementation" Bugzilla: 582475 RH-Acked-by: Paolo Bonzini RH-Acked-by: Marcelo Tosatti RH-Acked-by: Kevin Wolf From: Stefan Hajnoczi Before being able to apply upstream image streaming patches we need to revert the RHEL 6.2 image streaming code. This reverts commit 784aa9c6a1bb88aa3145bf31abc96e068fb0b5d6. Signed-off-by: Anthony Liguori Signed-off-by: Jeff Cody --- block/qed.c | 248 ++++------------------------------------------------------- block/qed.h | 3 +- 2 files changed, 17 insertions(+), 234 deletions(-) Signed-off-by: Michal Novotny --- block/qed.c | 248 ++++------------------------------------------------------- block/qed.h | 3 +- 2 files changed, 17 insertions(+), 234 deletions(-) diff --git a/block/qed.c b/block/qed.c index 3f11233..916ddd6 100644 --- a/block/qed.c +++ b/block/qed.c @@ -935,8 +935,9 @@ static void qed_aio_write_l1_update(void *opaque, int ret) /** * Update L2 table with new cluster offsets and write them out */ -static void qed_aio_write_l2_update(QEDAIOCB *acb, int ret, uint64_t offset) +static void qed_aio_write_l2_update(void *opaque, int ret) { + QEDAIOCB *acb = opaque; BDRVQEDState *s = acb_to_s(acb); bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1; int index; @@ -952,7 +953,7 @@ static void qed_aio_write_l2_update(QEDAIOCB *acb, int ret, uint64_t offset) index = qed_l2_index(s, acb->cur_pos); qed_update_l2_table(s, acb->request.l2_table->table, index, acb->cur_nclusters, - offset); + acb->cur_cluster); if (need_alloc) { /* Write out the whole new L2 table */ @@ -969,51 +970,6 @@ err: qed_aio_complete(acb, ret); } -static void qed_aio_write_l2_update_cb(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - qed_aio_write_l2_update(acb, ret, acb->cur_cluster); -} - -/** - * Determine if we have a zero write to a block of clusters - * - * We validate that the write is aligned to a cluster boundary, and that it's - * a multiple of cluster size with all zeros. - */ -static bool qed_is_zero_write(QEDAIOCB *acb) -{ - BDRVQEDState *s = acb_to_s(acb); - int i; - - if (!qed_offset_is_cluster_aligned(s, acb->cur_pos)) { - return false; - } - - if (!qed_offset_is_cluster_aligned(s, acb->cur_qiov.size)) { - return false; - } - - for (i = 0; i < acb->cur_qiov.niov; i++) { - struct iovec *iov = &acb->cur_qiov.iov[i]; - uint64_t *v; - int j; - - if ((iov->iov_len & 0x07)) { - return false; - } - - v = iov->iov_base; - for (j = 0; j < iov->iov_len; j += sizeof(v[0])) { - if (v[j >> 3]) { - return false; - } - } - } - - return true; -} - /** * Flush new data clusters before updating the L2 table * @@ -1028,7 +984,7 @@ static void qed_aio_write_flush_before_l2_update(void *opaque, int ret) QEDAIOCB *acb = opaque; BDRVQEDState *s = acb_to_s(acb); - if (!bdrv_aio_flush(s->bs->file, qed_aio_write_l2_update_cb, opaque)) { + if (!bdrv_aio_flush(s->bs->file, qed_aio_write_l2_update, opaque)) { qed_aio_complete(acb, -EIO); } } @@ -1058,7 +1014,7 @@ static void qed_aio_write_main(void *opaque, int ret) if (s->bs->backing_hd) { next_fn = qed_aio_write_flush_before_l2_update; } else { - next_fn = qed_aio_write_l2_update_cb; + next_fn = qed_aio_write_l2_update; } } @@ -1124,18 +1080,6 @@ static bool qed_should_set_need_check(BDRVQEDState *s) return !(s->header.features & QED_F_NEED_CHECK); } -static void qed_aio_write_zero_cluster(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - - if (ret) { - qed_aio_complete(acb, ret); - return; - } - - qed_aio_write_l2_update(acb, 0, 1); -} - /** * Start an allocating write request or queue it * @@ -1176,7 +1120,6 @@ static bool qed_start_allocating_write(QEDAIOCB *acb) static void qed_aio_write_alloc(QEDAIOCB *acb) { BDRVQEDState *s = acb_to_s(acb); - BlockDriverCompletionFunc *cb; if (!qed_start_allocating_write(acb)) { qemu_iovec_reset(&acb->cur_qiov); @@ -1187,18 +1130,11 @@ static void qed_aio_write_alloc(QEDAIOCB *acb) qed_offset_into_cluster(s, acb->cur_pos) + acb->cur_qiov.size); acb->cur_cluster = qed_alloc_clusters(s, acb->cur_nclusters); - cb = qed_aio_write_prefill; - - /* Zero write detection */ - if ((acb->flags & QED_AIOCB_CHECK_ZERO_WRITE) && qed_is_zero_write(acb)) { - cb = qed_aio_write_zero_cluster; - } - if (qed_should_set_need_check(s)) { s->header.features |= QED_F_NEED_CHECK; - qed_write_header(s, cb, acb); + qed_write_header(s, qed_aio_write_prefill, acb); } else { - cb(acb, 0); + qed_aio_write_prefill(acb, 0); } } @@ -1355,11 +1291,11 @@ static void qed_aio_next_io(void *opaque, int ret) io_fn, acb); } -static QEDAIOCB *qed_aio_setup(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, int flags) +static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, + void *opaque, int flags) { QEDAIOCB *acb = qemu_aio_get(&qed_aio_pool, bs, cb, opaque); @@ -1375,22 +1311,8 @@ static QEDAIOCB *qed_aio_setup(BlockDriverState *bs, acb->request.l2_table = NULL; qemu_iovec_init(&acb->cur_qiov, qiov->niov); - return acb; -} - -static BlockDriverAIOCB *bdrv_qed_aio_setup(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, int flags) -{ - QEDAIOCB *acb; - - acb = qed_aio_setup(bs, sector_num, qiov, nb_sectors, - cb, opaque, flags); /* Start request */ qed_aio_next_io(acb, 0); - return &acb->common; } @@ -1400,15 +1322,9 @@ static BlockDriverAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { - /* Don't bloat image file in copy-on-read, use zero detection */ - int flags = QED_AIOCB_CHECK_ZERO_WRITE; - - if (bs->copy_on_read) { - flags |= QED_AIOCB_COPY_ON_READ; - } + int flags = bs->copy_on_read ? QED_AIOCB_COPY_ON_READ : 0; - return bdrv_qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, - opaque, flags); + return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, flags); } static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs, @@ -1417,139 +1333,8 @@ static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { - return bdrv_qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, - opaque, QED_AIOCB_WRITE); -} - -typedef struct QEDCopyBackingData { - QEDAIOCB *acb; - uint64_t offset; - QEMUIOVector qiov; - void *buffer; - size_t len; - BlockDriverCompletionFunc *cb; - void *opaque; -} QEDCopyBackingData; - -static void qed_aio_copy_backing_cb(void *opaque, int ret) -{ - QEDCopyBackingData *copy_backing_data = opaque; - QEDAIOCB *acb = copy_backing_data->acb; - - if (ret) { - ret = -EIO; - } else { - ret = (acb->end_pos - copy_backing_data->offset) / BDRV_SECTOR_SIZE; - } - - copy_backing_data->cb(copy_backing_data->opaque, ret); - - qemu_iovec_destroy(©_backing_data->qiov); - qemu_vfree(copy_backing_data->buffer); - g_free(copy_backing_data); -} - -static void qed_copy_backing_find_cluster_cb(void *opaque, int ret, - uint64_t offset, size_t len); - -/** - * Perform the next qed_find_cluster() from a BH - * - * This is necessary because we iterate over each cluster in turn. - * qed_find_cluster() may invoke its callback immediately without returning up - * the call stack, causing us to overflow the call stack. By starting each - * iteration from a BH we guarantee that a fresh stack is used each time. - */ -static void qed_copy_backing_next_cluster_bh(void *opaque) -{ - QEDCopyBackingData *copy_backing_data = opaque; - QEDAIOCB *acb = copy_backing_data->acb; - BDRVQEDState *s = acb_to_s(acb); - - qemu_bh_delete(acb->bh); - acb->bh = NULL; - - acb->cur_pos += s->header.cluster_size; - acb->end_pos += s->header.cluster_size; - - qed_find_cluster(s, &acb->request, acb->cur_pos, - acb->end_pos - acb->cur_pos, - qed_copy_backing_find_cluster_cb, copy_backing_data); -} - -/** - * Search for an unallocated cluster adjusting the current request until we - * can use it to read an unallocated cluster. - * - * Callback from qed_find_cluster(). - */ -static void qed_copy_backing_find_cluster_cb(void *opaque, int ret, - uint64_t offset, size_t len) -{ - QEDCopyBackingData *copy_backing_data = opaque; - QEDAIOCB *acb = copy_backing_data->acb; - BDRVQEDState *s = acb_to_s(acb); - - if (ret < 0) { - qed_aio_complete(acb, ret); - return; - } - - if (ret == QED_CLUSTER_FOUND || - ret == QED_CLUSTER_ZERO) { - /* proceed to next cluster */ - - if (acb->end_pos == s->header.image_size) { - qed_aio_complete(acb, 0); - return; - } - - acb->bh = qemu_bh_new(qed_copy_backing_next_cluster_bh, - copy_backing_data); - qemu_bh_schedule(acb->bh); - } else { - /* found a hole, kick off request */ - qed_aio_next_io(acb, 0); - } -} - -static BlockDriverAIOCB *bdrv_qed_aio_copy_backing(BlockDriverState *bs, - int64_t sector_num, BlockDriverCompletionFunc *cb, void *opaque) -{ - BDRVQEDState *s = bs->opaque; - QEDCopyBackingData *copy_backing_data; - QEDAIOCB *acb; - uint32_t cluster_size = s->header.cluster_size; - uint64_t start_cluster; - QEMUIOVector *qiov; - - copy_backing_data = g_malloc0(sizeof(*copy_backing_data)); - - copy_backing_data->cb = cb; - copy_backing_data->opaque = opaque; - copy_backing_data->len = cluster_size; - copy_backing_data->buffer = qemu_blockalign(s->bs, cluster_size); - copy_backing_data->offset = sector_num * BDRV_SECTOR_SIZE; - - start_cluster = qed_start_of_cluster(s, copy_backing_data->offset); - sector_num = start_cluster / BDRV_SECTOR_SIZE; - - qiov = ©_backing_data->qiov; - qemu_iovec_init(qiov, 1); - qemu_iovec_add(qiov, copy_backing_data->buffer, cluster_size); - - acb = qed_aio_setup(bs, sector_num, qiov, - cluster_size / BDRV_SECTOR_SIZE, - qed_aio_copy_backing_cb, copy_backing_data, - QED_AIOCB_CHECK_ZERO_WRITE | - QED_AIOCB_COPY_ON_READ); - copy_backing_data->acb = acb; - - qed_find_cluster(s, &acb->request, acb->cur_pos, - acb->end_pos - acb->cur_pos, - qed_copy_backing_find_cluster_cb, copy_backing_data); - - return &acb->common; + return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, + opaque, QED_AIOCB_WRITE); } static BlockDriverAIOCB *bdrv_qed_aio_flush(BlockDriverState *bs, @@ -1714,7 +1499,6 @@ static BlockDriver bdrv_qed = { .bdrv_make_empty = bdrv_qed_make_empty, .bdrv_aio_readv = bdrv_qed_aio_readv, .bdrv_aio_writev = bdrv_qed_aio_writev, - .bdrv_aio_copy_backing = bdrv_qed_aio_copy_backing, .bdrv_aio_flush = bdrv_qed_aio_flush, .bdrv_truncate = bdrv_qed_truncate, .bdrv_getlength = bdrv_qed_getlength, diff --git a/block/qed.h b/block/qed.h index 48c65f7..16f4bd9 100644 --- a/block/qed.h +++ b/block/qed.h @@ -124,9 +124,8 @@ typedef struct QEDRequest { } QEDRequest; enum { - QED_AIOCB_WRITE = 0x0001, /* read or write? */ + QED_AIOCB_WRITE = 0x0001, /* read or write? */ QED_AIOCB_COPY_ON_READ = 0x0002, - QED_AIOCB_CHECK_ZERO_WRITE = 0x0004, /* detect zeroes? */ }; typedef struct QEDAIOCB { -- 1.7.7.6