Patchwork [RFC,19/24] qcow2: add qcow2_copy_header()

login
register
mail settings
Submitter Devin Nakamura
Date July 29, 2011, 4:49 a.m.
Message ID <1311914994-20482-20-git-send-email-devin122@gmail.com>
Download mbox | patch
Permalink /patch/107332/
State New
Headers show

Comments

Devin Nakamura - July 29, 2011, 4:49 a.m.
Signed-off-by: Devin Nakamura <devin122@gmail.com>
---
 block/qcow2.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)
Kevin Wolf - Aug. 1, 2011, 2:57 p.m.
Am 29.07.2011 06:49, schrieb Devin Nakamura:
> Signed-off-by: Devin Nakamura <devin122@gmail.com>
> ---
>  block/qcow2.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 54 insertions(+), 0 deletions(-)

Do we really need to build a completely new header? We should already
have one at a different offset that we only need to copy, no?

Kevin

Patch

diff --git a/block/qcow2.c b/block/qcow2.c
index b75364d..3bb28d2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1374,6 +1374,59 @@  static int qcow2_get_mapping(BlockDriverState *bs, uint64_t *guest_offset,
     return 0;
 }
 
+static int qcow2_copy_header(BlockDriverState *bs)
+{
+    BlockDriverState *backup;
+    uint8_t buffer[512];
+    int ret;
+    QCowHeader header;
+    BDRVQcowState *s = bs->opaque;
+    ret = qcow2_cache_flush(bs, s->l2_table_cache);
+    if (ret) {
+        return ret;
+    }
+
+    /*TODO: change filename*/
+    bdrv_create_file("headerbackup.temp", NULL);
+    bdrv_file_open(&backup, "headerbackup.temp", BDRV_O_RDWR);
+    bdrv_read(bs->file, 0, buffer, 1); /*TODO: check return code*/
+    bdrv_write(backup, 0, buffer, 1); /*TODO: check return code*/
+    bdrv_close(backup);
+
+    header.magic = QCOW_MAGIC;
+    header.version = 2;
+    header.backing_file_offset = 0;
+    header.backing_file_size = 0;
+    header.size = bs->total_sectors << BDRV_SECTOR_BITS;
+    header.cluster_bits = s->cluster_bits;
+    header.crypt_method = QCOW_CRYPT_NONE;
+    header.l1_table_offset = s->l1_table_offset;
+    header.l1_size = s->l1_size;
+    header.refcount_table_offset = s->refcount_table_offset;
+    header.refcount_table_clusters = s->refcount_table_size; /*TODO: FIXME*/
+    header.snapshots_offset = s->snapshots_offset;
+    header.nb_snapshots = s->nb_snapshots;
+
+    cpu_to_be64s(&header.backing_file_offset);
+    cpu_to_be32s(&header.backing_file_size);
+    cpu_to_be32s(&header.cluster_bits);
+    cpu_to_be32s(&header.crypt_method);
+    cpu_to_be32s(&header.l1_size);
+    cpu_to_be64s(&header.l1_table_offset);
+    cpu_to_be32s(&header.magic);
+    cpu_to_be32s(&header.nb_snapshots);
+    cpu_to_be32s(&header.refcount_table_clusters);
+    cpu_to_be64s(&header.refcount_table_offset);
+    cpu_to_be64s(&header.size);
+    cpu_to_be64s(&header.snapshots_offset);
+    cpu_to_be32s(&header.version);
+    ret = bdrv_pwrite_sync(bs->file, 0, &header, sizeof(QCowHeader));
+    if (ret) {
+        return ret;
+    }
+    return qcow2_drop_leaked_clusters(bs);
+}
+
 static QEMUOptionParameter qcow2_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -1446,6 +1499,7 @@  static BlockDriver bdrv_qcow2 = {
 
     .bdrv_get_mapping = qcow2_get_mapping,
     .bdrv_map         = qcow2_map,
+    .bdrv_copy_header = qcow2_copy_header,
 };
 
 static void bdrv_qcow2_init(void)