[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 21/24] qcow2: add qcow2_open_conversion_target()
From: |
Devin Nakamura |
Subject: |
[Qemu-devel] [RFC 21/24] qcow2: add qcow2_open_conversion_target() |
Date: |
Fri, 29 Jul 2011 00:49:51 -0400 |
Still in very raw form. Not likely to work yet
Signed-off-by: Devin Nakamura <address@hidden>
---
block/qcow2.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 124 insertions(+), 0 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 86df65d..f1e1e12 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1444,6 +1444,129 @@ static int
qcow2_get_conversion_options(BlockDriverState *bs,
}
return 0;
}
+
+
+static int qcow2_open_conversion_target(BlockDriverState *bs,
+ BlockConversionOptions *drv_options,
+ QEMUOptionParameter *usr_options)
+{
+ uint64_t imgsize, sectorsize, clusterbits;
+ uint64_t num_refcount_blocks;
+ uint16_t *refcount_block;
+ uint64_t table_index, table_limit, i;
+
+ sectorsize = drv_options->cluster_size;
+ clusterbits = 0;
+ while (~sectorsize & 1) {
+ sectorsize >>=1;
+ clusterbits++;
+ }
+ if (sectorsize != 1) {
+ return -EINVAL;
+ }
+
+
+ imgsize = drv_options->image_size;
+
+ BDRVQcowState *s = bs->opaque;
+ s->crypt_method_header = QCOW_CRYPT_NONE;
+ s->cluster_bits = clusterbits;
+ s->cluster_size = 1 << s->cluster_bits;
+ s->cluster_sectors = 1 << (s->cluster_bits - 9);
+ s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
+ s->l2_size = 1 << s->l2_bits;
+ bs->total_sectors = imgsize / 512;
+ s->csize_shift = (62 - (s->cluster_bits - 8));
+ s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
+ s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
+ //s->refcount_table_offset = 0;
+ //s->refcount_table_size = 0;
+ s->snapshots_offset = 0;
+ s->nb_snapshots = 0;
+ /* alloc L2 table/refcount block cache */
+ s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE, true); //todo:
double check writethrough
+ s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE,
+ true);
+
+ s->cluster_cache = qemu_malloc(s->cluster_size);
+ /* one more sector for decompressed data alignment */
+ s->cluster_data = qemu_malloc(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
+ + 512);
+ s->cluster_cache_offset = -1;
+
+ //Make up a refcount table
+ const uint64_t num_clusters = bs->file->total_sectors >>
+ (clusterbits - BDRV_SECTOR_BITS);
+ const uint64_t cluster_size = 1 << s->cluster_bits;
+ const uint64_t uint64_per_cluster = cluster_size / sizeof(uint64_t);
+ const uint64_t uint16_per_cluster = cluster_size / sizeof(uint16_t);
+ const uint64_t num_l2_tables = (num_clusters + uint64_per_cluster - 1) /
+ uint64_per_cluster;
+ const uint64_t num_l1_clusters = (num_l2_tables + uint64_per_cluster - 1)
+ / uint64_per_cluster);
+ s->l1_size = num_l2_tables;
+ s->l1_table = qemu_mallocz(s->l1_size * s->cluster_size);
+ num_refcount_blocks = num_clusters + num_l2_tables + num_l1_clusters;
+ num_refcount_blocks = (num_refcount_blocks + uint16_per_cluster - 1) /
+ uint16_per_cluster;
+
+ /* Account for refcount blocks used to track refcount blocks */
+ num_refcount_blocks *= uint16_per_cluster;
+ num_refcount_blocks /= uint16_per_cluster -1;
+ num_refcount_blocks += 1; //todo: fix rounding
+
+ /* Account for refcount blocks used to track refcount table */
+ num_refcount_blocks *= uint64_per_cluster;
+ num_refcount_blocks /= uint64_per_cluster -1;
+ num_refcount_blocks += 1; // todo: fix rounding
+
+ s->refcount_table_size = (num_refcount_blocks / uint64_per_cluster) +1;
+ s->refcount_table = qemu_mallocz(s->refcount_table_size * s->cluster_size);
+ refcount_block = qemu_mallocz(s->cluster_size);
+
+// s->refcount_table_size = num_refcount_blocks;
+ s->free_cluster_index = num_clusters;
+ s->l1_table_offset = s->free_cluster_index << s->cluster_bits;
+ s->free_cluster_index += num_l1_clusters;
+ s->refcount_table_offset = s->free_cluster_index << s->cluster_bits;
+ s->free_cluster_index++;
+
+ /* assign offsets for all refcount blocks */
+ for (table_index = 0; table_index < num_refcount_blocks; table_index++) {
+ s->refcount_table[table_index] = s->free_cluster_index++ <<
s->cluster_bits;
+ }
+
+ /* set all refcounts in the block to 1 */
+ for (i=0; i < uint16_per_cluster; i++) {
+ refcount_block[i] = cpu_to_be16(1);
+ }
+
+ //TODO: double check this, it seems a bit fishy
+ table_limit = s->free_cluster_index / uint16_per_cluster;
+ for(table_index = 0; table_index < table_limit; table_index++) {
+ bdrv_write_sync(bs->file, s->refcount_table[table_index] >>
BDRV_SECTOR_BITS,
+ (uint8_t*) refcount_block, s->cluster_sectors);
+ }
+
+ table_limit = s->free_cluster_index % uint16_per_cluster;
+ for(i=table_limit; i < uint64_per_cluster; i++) {
+ refcount_block[i] = 0;
+ }
+ bdrv_write_sync(bs->file, s->refcount_table[table_index] >>
BDRV_SECTOR_BITS,
+ (uint8_t*) refcount_block, s->cluster_sectors);
+ uint64_t* be_refcount_table = qemu_mallocz(s->refcount_table_size *
s->cluster_size);
+ for(i=0; i < s->refcount_table_size; i++) {
+ be_refcount_table[i] = cpu_to_be64(s->refcount_table[i]);
+ }
+ bdrv_write_sync(bs->file, s->refcount_table_offset >> BDRV_SECTOR_BITS,
+ (uint8_t*)be_refcount_table,s->refcount_table_size *
s->cluster_size);
+ QLIST_INIT(&s->cluster_allocs);
+
+ qemu_free(refcount_block);
+ return 0;
+}
+
+
static QEMUOptionParameter qcow2_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
@@ -1518,6 +1641,7 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_map = qcow2_map,
.bdrv_copy_header = qcow2_copy_header,
.bdrv_get_conversion_options = qcow2_get_conversion_options,
+ .bdrv_open_conversion_target = qcow2_open_conversion_target,
};
static void bdrv_qcow2_init(void)
--
1.7.6.rc1
- [Qemu-devel] [RFC 11/24] qed: add open_conversion_target(), (continued)
- [Qemu-devel] [RFC 11/24] qed: add open_conversion_target(), Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 09/24] qed: add qed_bdrv_get_mapping(), Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 13/24] qed: add bdrv_qed_get_conversion_options(), Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 12/24] qed: add bdrv_qed_copy_header(), Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 15/24] qcow2: split up the creation of new refcount table from the act of checking it, Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 14/24] qcow2: fix typo in documentation for qcow2_get_cluster_offset(), Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 16/24] qcow2: add qcow2_drop_leaked_clusters(), Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 17/24] qcow2: add qcow2_get_mapping, Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 18/24] qcow2: add qcow2_map, Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 19/24] qcow2: add qcow2_copy_header(), Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 21/24] qcow2: add qcow2_open_conversion_target(),
Devin Nakamura <=
- [Qemu-devel] [RFC 23/24] qemu-io: add setmap command, Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 24/24] qemu-img: add inplace conversion to qemu-img, Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 22/24] qemu-io: make map command use new block mapping function, Devin Nakamura, 2011/07/29
- [Qemu-devel] [RFC 20/24] qcow2: add get_conversion_options(), Devin Nakamura, 2011/07/29