cryptospore / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-block-vhdx-break-out-code-operations-to-functions.patch

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