This needs to be reworked. It was a mostly automatic conversion that hasn't had a review and with just some fixes in places where things broke. It was good enough for some testing, though. --- block/qcow2-cluster.c | 39 +++++++++++++++-------------- block/qcow2-refcount.c | 62 ++++++++++++++++++++++++------------------------ block/qcow2.c | 18 +++++++++++++- block/qcow2.h | 4 +++ 4 files changed, 72 insertions(+), 51 deletions(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 4f7dc59..9f81593 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -67,12 +67,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size) qemu_free(new_l1_table); return new_l1_table_offset; } - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE); for(i = 0; i < s->l1_size; i++) new_l1_table[i] = cpu_to_be64(new_l1_table[i]); - ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset, new_l1_table, new_l1_size2); + ret = blkqueue_pwrite(&s->bq_context, new_l1_table_offset, new_l1_table, new_l1_size2); + blkqueue_barrier(&s->bq_context); if (ret < 0) goto fail; for(i = 0; i < s->l1_size; i++) @@ -82,7 +83,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size) BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE); cpu_to_be32w((uint32_t*)data, new_l1_size); cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset); - ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size), data,sizeof(data)); + ret = blkqueue_pwrite(&s->bq_context, offsetof(QCowHeader, l1_size), data, sizeof(data)); + blkqueue_barrier(&s->bq_context); if (ret < 0) { goto fail; } @@ -185,8 +187,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset, *l2_table = s->l2_cache + (min_index << s->l2_bits); BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD); - ret = bdrv_pread(bs->file, l2_offset, *l2_table, - s->l2_size * sizeof(uint64_t)); + ret = blkqueue_pread(&s->bq_context, l2_offset, *l2_table, s->l2_size * sizeof(uint64_t)); if (ret < 0) { return ret; } @@ -215,8 +216,8 @@ static int write_l1_entry(BlockDriverState *bs, int l1_index) } BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); - ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset + 8 * l1_start_index, - buf, sizeof(buf)); + ret = blkqueue_pwrite(&s->bq_context, s->l1_table_offset + 8 * l1_start_index, buf, sizeof(buf)); + blkqueue_barrier(&s->bq_context); if (ret < 0) { return ret; } @@ -251,7 +252,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) if (l2_offset < 0) { return l2_offset; } - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); /* allocate a new entry in the l2 cache */ @@ -264,16 +265,15 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) } else { /* if there was an old l2 table, read it from the disk */ BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ); - ret = bdrv_pread(bs->file, old_l2_offset, l2_table, - s->l2_size * sizeof(uint64_t)); + ret = blkqueue_pread(&s->bq_context, old_l2_offset, l2_table, s->l2_size * sizeof(uint64_t)); if (ret < 0) { goto fail; } } /* write the l2 table to the file */ BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE); - ret = bdrv_pwrite_sync(bs->file, l2_offset, l2_table, - s->l2_size * sizeof(uint64_t)); + ret = blkqueue_pwrite(&s->bq_context, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)); + blkqueue_barrier(&s->bq_context); if (ret < 0) { goto fail; } @@ -393,8 +393,8 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num, memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n); } else { BLKDBG_EVENT(bs->file, BLKDBG_READ); - ret = bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512); - if (ret != n * 512) + ret = blkqueue_pread(&s->bq_context, cluster_offset + index_in_cluster * 512, buf, n * 512); + if (ret < 0) return -1; if (s->crypt_method) { qcow2_encrypt_sectors(s, sector_num, buf, buf, n, 0, @@ -646,11 +646,12 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); l2_table[l2_index] = cpu_to_be64(cluster_offset); - if (bdrv_pwrite_sync(bs->file, + if (blkqueue_pwrite(&s->bq_context, l2_offset + l2_index * sizeof(uint64_t), l2_table + l2_index, sizeof(uint64_t)) < 0) return 0; + blkqueue_barrier(&s->bq_context); return cluster_offset; } @@ -663,6 +664,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table, uint64_t l2_offset, int l2_index, int num) { + BDRVQcowState *s = bs->opaque; int l2_start_index = l2_index & ~(L1_ENTRIES_PER_SECTOR - 1); int start_offset = (8 * l2_index) & ~511; int end_offset = (8 * (l2_index + num) + 511) & ~511; @@ -670,8 +672,7 @@ static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table, int ret; BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); - ret = bdrv_pwrite(bs->file, l2_offset + start_offset, - &l2_table[l2_start_index], len); + ret = blkqueue_pwrite(&s->bq_context, l2_offset + start_offset, &l2_table[l2_start_index], len); if (ret < 0) { return ret; } @@ -732,7 +733,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) * need to be sure that the refcounts have been increased and COW was * handled. */ - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); ret = write_l2_entries(bs, l2_table, l2_offset, l2_index, m->nb_clusters); if (ret < 0) { @@ -745,7 +746,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) * Also flush bs->file to get the right order for L2 and refcount update. */ if (j != 0) { - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); for (i = 0; i < j; i++) { qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1); diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 0efb676..ca2cc4d 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -44,7 +44,7 @@ static int write_refcount_block(BlockDriverState *bs) } BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE); - if (bdrv_pwrite_sync(bs->file, s->refcount_block_cache_offset, + if (blkqueue_pwrite(&s->bq_context, s->refcount_block_cache_offset, s->refcount_block_cache, size) < 0) { return -EIO; @@ -66,8 +66,7 @@ int qcow2_refcount_init(BlockDriverState *bs) s->refcount_table = qemu_malloc(refcount_table_size2); if (s->refcount_table_size > 0) { BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD); - ret = bdrv_pread(bs->file, s->refcount_table_offset, - s->refcount_table, refcount_table_size2); + ret = bdrv_pread(bs->file, s->refcount_table_offset, s->refcount_table, refcount_table_size2); if (ret != refcount_table_size2) goto fail; for(i = 0; i < s->refcount_table_size; i++) @@ -100,8 +99,7 @@ static int load_refcount_block(BlockDriverState *bs, } BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_LOAD); - ret = bdrv_pread(bs->file, refcount_block_offset, s->refcount_block_cache, - s->cluster_size); + ret = blkqueue_pread(&s->bq_context, refcount_block_offset, s->refcount_block_cache, s->cluster_size); if (ret < 0) { return ret; } @@ -261,7 +259,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) goto fail_block; } - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); /* Initialize the new refcount block only after updating its refcount, * update_refcount uses the refcount cache itself */ @@ -271,8 +269,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) /* Now the new refcount block needs to be written to disk */ BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE); - ret = bdrv_pwrite_sync(bs->file, new_block, s->refcount_block_cache, - s->cluster_size); + ret = blkqueue_pwrite(&s->bq_context, new_block, s->refcount_block_cache, s->cluster_size); + blkqueue_barrier(&s->bq_context); if (ret < 0) { goto fail_block; } @@ -281,9 +279,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) if (refcount_table_index < s->refcount_table_size) { uint64_t data64 = cpu_to_be64(new_block); BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP); - ret = bdrv_pwrite_sync(bs->file, - s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), - &data64, sizeof(data64)); + ret = blkqueue_pwrite(&s->bq_context, s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), &data64, sizeof(data64)); + blkqueue_barrier(&s->bq_context); if (ret < 0) { goto fail_block; } @@ -361,8 +358,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) /* Write refcount blocks to disk */ BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS); - ret = bdrv_pwrite_sync(bs->file, meta_offset, new_blocks, - blocks_clusters * s->cluster_size); + ret = blkqueue_pwrite(&s->bq_context, meta_offset, new_blocks, blocks_clusters * s->cluster_size); + blkqueue_barrier(&s->bq_context); qemu_free(new_blocks); if (ret < 0) { goto fail_table; @@ -374,8 +371,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) } BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE); - ret = bdrv_pwrite_sync(bs->file, table_offset, new_table, - table_size * sizeof(uint64_t)); + ret = blkqueue_pwrite(&s->bq_context, table_offset, new_table, table_size * sizeof(uint64_t)); + blkqueue_barrier(&s->bq_context); if (ret < 0) { goto fail_table; } @@ -389,8 +386,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) cpu_to_be64w((uint64_t*)data, table_offset); cpu_to_be32w((uint32_t*)(data + 8), table_clusters); BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE); - ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, refcount_table_offset), - data, sizeof(data)); + ret = blkqueue_pwrite(&s->bq_context, offsetof(QCowHeader, refcount_table_offset), data, sizeof(data)); + blkqueue_barrier(&s->bq_context); if (ret < 0) { goto fail_table; } @@ -446,9 +443,7 @@ static int write_refcount_block_entries(BlockDriverState *bs, size = (last_index - first_index) << REFCOUNT_SHIFT; BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART); - ret = bdrv_pwrite(bs->file, - refcount_block_offset + (first_index << REFCOUNT_SHIFT), - &s->refcount_block_cache[first_index], size); + ret = blkqueue_pwrite(&s->bq_context, refcount_block_offset + (first_index << REFCOUNT_SHIFT), &s->refcount_block_cache[first_index], size); if (ret < 0) { return ret; } @@ -576,7 +571,7 @@ static int update_cluster_refcount(BlockDriverState *bs, return ret; } - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); return get_refcount(bs, cluster_index); } @@ -678,7 +673,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) } } - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); return offset; } @@ -771,8 +766,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, l1_table = NULL; } l1_allocated = 1; - if (bdrv_pread(bs->file, l1_table_offset, - l1_table, l1_size2) != l1_size2) + if (blkqueue_pread(&s->bq_context, l1_table_offset, l1_table, l1_size2) < 0) goto fail; for(i = 0;i < l1_size; i++) be64_to_cpus(&l1_table[i]); @@ -791,7 +785,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, old_l2_offset = l2_offset; l2_offset &= ~QCOW_OFLAG_COPIED; l2_modified = 0; - if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size) + if (blkqueue_pread(&s->bq_context, l2_offset, l2_table, l2_size) < 0) goto fail; for(j = 0; j < s->l2_size; j++) { offset = be64_to_cpu(l2_table[j]); @@ -812,7 +806,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, /* TODO Flushing once for the whole function should * be enough */ - bdrv_flush(bs->file); + blkqueue_barrier(&s->bq_context); } /* compressed clusters are never modified */ refcount = 2; @@ -838,9 +832,10 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } } if (l2_modified) { - if (bdrv_pwrite_sync(bs->file, + if (blkqueue_pwrite(&s->bq_context, l2_offset, l2_table, l2_size) < 0) goto fail; + blkqueue_barrier(&s->bq_context); } if (addend != 0) { @@ -862,9 +857,10 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, if (l1_modified) { for(i = 0; i < l1_size; i++) cpu_to_be64s(&l1_table[i]); - if (bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, + if (blkqueue_pwrite(&s->bq_context, l1_table_offset, l1_table, l1_size2) < 0) goto fail; + blkqueue_barrier(&s->bq_context); for(i = 0; i < l1_size; i++) be64_to_cpus(&l1_table[i]); } @@ -955,8 +951,9 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, l2_size = s->l2_size * sizeof(uint64_t); l2_table = qemu_malloc(l2_size); - if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size) + if (blkqueue_pread(&s->bq_context, l2_offset, l2_table, l2_size) < 0) { goto fail; + } /* Do the actual checks */ for(i = 0; i < s->l2_size; i++) { @@ -1050,9 +1047,10 @@ static int check_refcounts_l1(BlockDriverState *bs, l1_table = NULL; } else { l1_table = qemu_malloc(l1_size2); - if (bdrv_pread(bs->file, l1_table_offset, - l1_table, l1_size2) != l1_size2) + if (blkqueue_pread(&s->bq_context, l1_table_offset, l1_table, l1_size2) < 0) { goto fail; + } + for(i = 0;i < l1_size; i++) be64_to_cpus(&l1_table[i]); } @@ -1126,6 +1124,8 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res) nb_clusters = size_to_clusters(s, size); refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t)); + blkqueue_init_context(&s->bq_context, s->bq); + /* header */ inc_refcounts(bs, res, refcount_table, nb_clusters, 0, s->cluster_size); diff --git a/block/qcow2.c b/block/qcow2.c index b816d87..b76ce6b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -237,6 +237,10 @@ static int qcow_open(BlockDriverState *bs, int flags) if (qcow2_read_snapshots(bs) < 0) goto fail; + /* Block queue */ + s->bq = blkqueue_create(bs->file); + blkqueue_init_context(&s->bq_context, s->bq); + #ifdef DEBUG_ALLOC qcow2_check_refcounts(bs); #endif @@ -519,6 +523,7 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque, int is_write) { + BDRVQcowState *s = bs->opaque; QCowAIOCB *acb; acb = qemu_aio_get(&qcow_aio_pool, bs, cb, opaque); @@ -536,6 +541,10 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, acb->cluster_offset = 0; acb->l2meta.nb_clusters = 0; QLIST_INIT(&acb->l2meta.dependent_requests); + + /* TODO Push the context into l2meta */ + blkqueue_init_context(&s->bq_context, s->bq); + return acb; } @@ -694,6 +703,7 @@ static void qcow_close(BlockDriverState *bs) qemu_free(s->cluster_cache); qemu_free(s->cluster_data); qcow2_refcount_close(bs); + blkqueue_destroy(s->bq); } /* @@ -1150,13 +1160,19 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, static void qcow_flush(BlockDriverState *bs) { + BDRVQcowState *s = bs->opaque; + blkqueue_flush(s->bq); bdrv_flush(bs->file); } static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { - return bdrv_aio_flush(bs->file, cb, opaque); + BDRVQcowState *s = bs->opaque; + BlockQueueContext context; + + blkqueue_init_context(&context, s->bq); + return blkqueue_aio_flush(&context, cb, opaque); } static int64_t qcow_vm_state_offset(BDRVQcowState *s) diff --git a/block/qcow2.h b/block/qcow2.h index 2d22e5e..75b00a6 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -26,6 +26,7 @@ #define BLOCK_QCOW2_H #include "aes.h" +#include "block-queue.h" //#define DEBUG_ALLOC //#define DEBUG_ALLOC2 @@ -108,6 +109,9 @@ typedef struct BDRVQcowState { int64_t free_cluster_index; int64_t free_byte_offset; + BlockQueue *bq; + BlockQueueContext bq_context; + uint32_t crypt_method; /* current crypt method, 0 if no key yet */ uint32_t crypt_method_header; AES_KEY aes_encrypt_key; -- 1.7.2.3