From: Devin Nakamura <devin122@gmail.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, Devin Nakamura <devin122@gmail.com>
Subject: [Qemu-devel] [RFC 21/24] qcow2: add qcow2_open_conversion_target()
Date: Fri, 29 Jul 2011 00:49:51 -0400 [thread overview]
Message-ID: <1311914994-20482-22-git-send-email-devin122@gmail.com> (raw)
In-Reply-To: <1311914994-20482-1-git-send-email-devin122@gmail.com>
Still in very raw form. Not likely to work yet
Signed-off-by: Devin Nakamura <devin122@gmail.com>
---
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
next prev parent reply other threads:[~2011-07-29 4:50 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-29 4:49 [Qemu-devel] [RFC 00/24] inplace image conversion Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 01/24] block: add block conversion api Devin Nakamura
2011-08-01 13:34 ` Kevin Wolf
2011-08-02 4:43 ` Devin Nakamura
2011-08-02 8:56 ` Stefan Hajnoczi
2011-08-02 9:24 ` Kevin Wolf
2011-07-29 4:49 ` [Qemu-devel] [RFC 02/24] block: add bdrv_get_conversion_options() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 03/24] block: add bdrv_open_conversion_target() Devin Nakamura
2011-08-01 13:42 ` Kevin Wolf
2011-08-02 8:57 ` Stefan Hajnoczi
2011-07-29 4:49 ` [Qemu-devel] [RFC 04/24] block: add bdrv_get_mapping() Devin Nakamura
2011-08-02 8:58 ` Stefan Hajnoczi
2011-07-29 4:49 ` [Qemu-devel] [RFC 05/24] block: add bdrv_map() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 06/24] block: add bdrv_copy_header() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 07/24] qed: make qed_alloc_clusters round up offset to nearest cluster Devin Nakamura
2011-08-01 13:51 ` Kevin Wolf
2011-07-29 4:49 ` [Qemu-devel] [RFC 08/24] qed: add qed_find_cluster_sync() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 09/24] qed: add qed_bdrv_get_mapping() Devin Nakamura
2011-08-02 8:59 ` Stefan Hajnoczi
2011-07-29 4:49 ` [Qemu-devel] [RFC 10/24] qed: add qed_bdrv_map() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 11/24] qed: add open_conversion_target() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 12/24] qed: add bdrv_qed_copy_header() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 13/24] qed: add bdrv_qed_get_conversion_options() Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 14/24] qcow2: fix typo in documentation for qcow2_get_cluster_offset() Devin Nakamura
2011-07-29 4:49 ` [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 4:49 ` [Qemu-devel] [RFC 16/24] qcow2: add qcow2_drop_leaked_clusters() Devin Nakamura
2011-08-01 14:18 ` Kevin Wolf
2011-07-29 4:49 ` [Qemu-devel] [RFC 17/24] qcow2: add qcow2_get_mapping Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 18/24] qcow2: add qcow2_map Devin Nakamura
2011-08-01 14:32 ` Kevin Wolf
[not found] ` <CAJ1AwB5ohCMOeSgcUKpKHbqGuK8Eioq5dr-z+a6+vGzdMrJJ6w@mail.gmail.com>
2011-08-02 8:05 ` Kevin Wolf
2011-07-29 4:49 ` [Qemu-devel] [RFC 19/24] qcow2: add qcow2_copy_header() Devin Nakamura
2011-08-01 14:57 ` Kevin Wolf
2011-07-29 4:49 ` [Qemu-devel] [RFC 20/24] qcow2: add get_conversion_options() Devin Nakamura
2011-07-29 4:49 ` Devin Nakamura [this message]
2011-08-01 15:26 ` [Qemu-devel] [RFC 21/24] qcow2: add qcow2_open_conversion_target() Kevin Wolf
2011-08-02 4:37 ` Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 22/24] qemu-io: make map command use new block mapping function Devin Nakamura
2011-08-01 15:38 ` Kevin Wolf
2011-08-02 4:02 ` Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 23/24] qemu-io: add setmap command Devin Nakamura
2011-07-29 4:49 ` [Qemu-devel] [RFC 24/24] qemu-img: add inplace conversion to qemu-img Devin Nakamura
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1311914994-20482-22-git-send-email-devin122@gmail.com \
--to=devin122@gmail.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).