qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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

  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).