yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
0a122b
From e9029068354e2c9dbfe7e7deaa6a96344a8b4d46 Mon Sep 17 00:00:00 2001
0a122b
From: Jeffrey Cody <jcody@redhat.com>
0a122b
Date: Wed, 20 Nov 2013 19:44:03 +0100
0a122b
Subject: [PATCH 20/25] block: vhdx - break out code operations to functions
0a122b
0a122b
RH-Author: Jeffrey Cody <jcody@redhat.com>
0a122b
Message-id: <7f3a67c6c0988ecccac88cc5a8985058611e4cfa.1384975172.git.jcody@redhat.com>
0a122b
Patchwork-id: 55815
0a122b
O-Subject: [RHEL7 qemu-kvm PATCH 20/26] block: vhdx - break out code operations to functions
0a122b
Bugzilla: 879234
0a122b
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
0a122b
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
0a122b
RH-Acked-by: Fam Zheng <famz@redhat.com>
0a122b
0a122b
This is preperation for vhdx_create().  The ability to write headers,
0a122b
and calculate the number of BAT entries will be needed within the
0a122b
create() functions, so move this relevant code into helper functions.
0a122b
0a122b
Signed-off-by: Jeff Cody <jcody@redhat.com>
0a122b
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
0a122b
(cherry picked from commit 1e74a971cb3229813112c74dca81e599812b66f3)
0a122b
---
0a122b
 block/vhdx.c | 121 +++++++++++++++++++++++++++++++++++++++--------------------
0a122b
 1 file changed, 80 insertions(+), 41 deletions(-)
0a122b
0a122b
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
0a122b
---
0a122b
 block/vhdx.c |  121 ++++++++++++++++++++++++++++++++++++++--------------------
0a122b
 1 files changed, 80 insertions(+), 41 deletions(-)
0a122b
0a122b
diff --git a/block/vhdx.c b/block/vhdx.c
0a122b
index 9d51176..5a112e8 100644
0a122b
--- a/block/vhdx.c
0a122b
+++ b/block/vhdx.c
0a122b
@@ -248,6 +248,14 @@ static void vhdx_region_unregister_all(BDRVVHDXState *s)
0a122b
     }
0a122b
 }
0a122b
 
0a122b
+static void vhdx_set_shift_bits(BDRVVHDXState *s)
0a122b
+{
0a122b
+    s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
0a122b
+    s->sectors_per_block_bits =   31 - clz32(s->sectors_per_block);
0a122b
+    s->chunk_ratio_bits =         63 - clz64(s->chunk_ratio);
0a122b
+    s->block_size_bits =          31 - clz32(s->block_size);
0a122b
+}
0a122b
+
0a122b
 /*
0a122b
  * Per the MS VHDX Specification, for every VHDX file:
0a122b
  *      - The header section is fixed size - 1 MB
0a122b
@@ -267,6 +275,50 @@ static int vhdx_probe(const uint8_t *buf, int buf_size, const char *filename)
0a122b
     return 0;
0a122b
 }
0a122b
 
0a122b
+/*
0a122b
+ * Writes the header to the specified offset.
0a122b
+ *
0a122b
+ * This will optionally read in buffer data from disk (otherwise zero-fill),
0a122b
+ * and then update the header checksum.  Header is converted to proper
0a122b
+ * endianness before being written to the specified file offset
0a122b
+ */
0a122b
+static int vhdx_write_header(BlockDriverState *bs_file, VHDXHeader *hdr,
0a122b
+                             uint64_t offset, bool read)
0a122b
+{
0a122b
+    uint8_t *buffer = NULL;
0a122b
+    int ret;
0a122b
+    VHDXHeader header_le;
0a122b
+
0a122b
+    assert(bs_file != NULL);
0a122b
+    assert(hdr != NULL);
0a122b
+
0a122b
+    /* the header checksum is not over just the packed size of VHDXHeader,
0a122b
+     * but rather over the entire 'reserved' range for the header, which is
0a122b
+     * 4KB (VHDX_HEADER_SIZE). */
0a122b
+
0a122b
+    buffer = qemu_blockalign(bs_file, VHDX_HEADER_SIZE);
0a122b
+    if (read) {
0a122b
+        /* if true, we can't assume the extra reserved bytes are 0 */
0a122b
+        ret = bdrv_pread(bs_file, offset, buffer, VHDX_HEADER_SIZE);
0a122b
+        if (ret < 0) {
0a122b
+            goto exit;
0a122b
+        }
0a122b
+    } else {
0a122b
+        memset(buffer, 0, VHDX_HEADER_SIZE);
0a122b
+    }
0a122b
+
0a122b
+    /* overwrite the actual VHDXHeader portion */
0a122b
+    memcpy(buffer, hdr, sizeof(VHDXHeader));
0a122b
+    hdr->checksum = vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
0a122b
+                                         offsetof(VHDXHeader, checksum));
0a122b
+    vhdx_header_le_export(hdr, &header_le);
0a122b
+    ret = bdrv_pwrite_sync(bs_file, offset, &header_le, sizeof(VHDXHeader));
0a122b
+
0a122b
+exit:
0a122b
+    qemu_vfree(buffer);
0a122b
+    return ret;
0a122b
+}
0a122b
+
0a122b
 /* Update the VHDX headers
0a122b
  *
0a122b
  * This follows the VHDX spec procedures for header updates.
0a122b
@@ -282,8 +334,6 @@ static int vhdx_update_header(BlockDriverState *bs, BDRVVHDXState *s,
0a122b
 
0a122b
     VHDXHeader *active_header;
0a122b
     VHDXHeader *inactive_header;
0a122b
-    VHDXHeader header_le;
0a122b
-    uint8_t *buffer;
0a122b
 
0a122b
     /* operate on the non-current header */
0a122b
     if (s->curr_header == 0) {
0a122b
@@ -311,31 +361,13 @@ static int vhdx_update_header(BlockDriverState *bs, BDRVVHDXState *s,
0a122b
         inactive_header->log_guid = *log_guid;
0a122b
     }
0a122b
 
0a122b
-    /* the header checksum is not over just the packed size of VHDXHeader,
0a122b
-     * but rather over the entire 'reserved' range for the header, which is
0a122b
-     * 4KB (VHDX_HEADER_SIZE). */
0a122b
-
0a122b
-    buffer = qemu_blockalign(bs, VHDX_HEADER_SIZE);
0a122b
-    /* we can't assume the extra reserved bytes are 0 */
0a122b
-    ret = bdrv_pread(bs->file, header_offset, buffer, VHDX_HEADER_SIZE);
0a122b
-    if (ret < 0) {
0a122b
-        goto exit;
0a122b
-    }
0a122b
-    /* overwrite the actual VHDXHeader portion */
0a122b
-    memcpy(buffer, inactive_header, sizeof(VHDXHeader));
0a122b
-    inactive_header->checksum =
0a122b
-                        vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
0a122b
-                                             offsetof(VHDXHeader, checksum));
0a122b
-    vhdx_header_le_export(inactive_header, &header_le);
0a122b
-    ret = bdrv_pwrite_sync(bs->file, header_offset, &header_le,
0a122b
-                           sizeof(VHDXHeader));
0a122b
+    vhdx_write_header(bs->file, inactive_header, header_offset, true);
0a122b
     if (ret < 0) {
0a122b
         goto exit;
0a122b
     }
0a122b
     s->curr_header = hdr_idx;
0a122b
 
0a122b
 exit:
0a122b
-    qemu_vfree(buffer);
0a122b
     return ret;
0a122b
 }
0a122b
 
0a122b
@@ -773,10 +805,7 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
0a122b
         goto exit;
0a122b
     }
0a122b
 
0a122b
-    s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
0a122b
-    s->sectors_per_block_bits =   31 - clz32(s->sectors_per_block);
0a122b
-    s->chunk_ratio_bits =         63 - clz64(s->chunk_ratio);
0a122b
-    s->block_size_bits =          31 - clz32(s->block_size);
0a122b
+    vhdx_set_shift_bits(s);
0a122b
 
0a122b
     ret = 0;
0a122b
 
0a122b
@@ -785,6 +814,31 @@ exit:
0a122b
     return ret;
0a122b
 }
0a122b
 
0a122b
+/*
0a122b
+ * Calculate the number of BAT entries, including sector
0a122b
+ * bitmap entries.
0a122b
+ */
0a122b
+static void vhdx_calc_bat_entries(BDRVVHDXState *s)
0a122b
+{
0a122b
+    uint32_t data_blocks_cnt, bitmap_blocks_cnt;
0a122b
+
0a122b
+    data_blocks_cnt = s->virtual_disk_size >> s->block_size_bits;
0a122b
+    if (s->virtual_disk_size - (data_blocks_cnt << s->block_size_bits)) {
0a122b
+        data_blocks_cnt++;
0a122b
+    }
0a122b
+    bitmap_blocks_cnt = data_blocks_cnt >> s->chunk_ratio_bits;
0a122b
+    if (data_blocks_cnt - (bitmap_blocks_cnt << s->chunk_ratio_bits)) {
0a122b
+        bitmap_blocks_cnt++;
0a122b
+    }
0a122b
+
0a122b
+    if (s->parent_entries) {
0a122b
+        s->bat_entries = bitmap_blocks_cnt * (s->chunk_ratio + 1);
0a122b
+    } else {
0a122b
+        s->bat_entries = data_blocks_cnt +
0a122b
+                         ((data_blocks_cnt - 1) >> s->chunk_ratio_bits);
0a122b
+    }
0a122b
+
0a122b
+}
0a122b
 
0a122b
 static void vhdx_close(BlockDriverState *bs)
0a122b
 {
0a122b
@@ -811,7 +865,6 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
0a122b
     int ret = 0;
0a122b
     uint32_t i;
0a122b
     uint64_t signature;
0a122b
-    uint32_t data_blocks_cnt, bitmap_blocks_cnt;
0a122b
     bool log_flushed = false;
0a122b
 
0a122b
 
0a122b
@@ -862,21 +915,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
0a122b
      * logical_sector_size */
0a122b
     bs->total_sectors = s->virtual_disk_size >> s->logical_sector_size_bits;
0a122b
 
0a122b
-    data_blocks_cnt = s->virtual_disk_size >> s->block_size_bits;
0a122b
-    if (s->virtual_disk_size - (data_blocks_cnt << s->block_size_bits)) {
0a122b
-        data_blocks_cnt++;
0a122b
-    }
0a122b
-    bitmap_blocks_cnt = data_blocks_cnt >> s->chunk_ratio_bits;
0a122b
-    if (data_blocks_cnt - (bitmap_blocks_cnt << s->chunk_ratio_bits)) {
0a122b
-        bitmap_blocks_cnt++;
0a122b
-    }
0a122b
-
0a122b
-    if (s->parent_entries) {
0a122b
-        s->bat_entries = bitmap_blocks_cnt * (s->chunk_ratio + 1);
0a122b
-    } else {
0a122b
-        s->bat_entries = data_blocks_cnt +
0a122b
-                         ((data_blocks_cnt - 1) >> s->chunk_ratio_bits);
0a122b
-    }
0a122b
+    vhdx_calc_bat_entries(s);
0a122b
 
0a122b
     s->bat_offset = s->bat_rt.file_offset;
0a122b
 
0a122b
-- 
0a122b
1.7.1
0a122b