cd9d16
From 5621e2027384a35494508f3bc01a758bc2ac076b Mon Sep 17 00:00:00 2001
cd9d16
From: Eric Sunshine <sunshine@sunshineco.com>
cd9d16
Date: Wed, 26 Oct 2011 15:51:18 -0400
cd9d16
Subject: [PATCH] Teach block/vdi about "discarded" (no longer allocated)
cd9d16
 blocks
cd9d16
MIME-Version: 1.0
cd9d16
Content-Type: text/plain; charset=UTF-8
cd9d16
Content-Transfer-Encoding: 8bit
cd9d16
cd9d16
An entry in the VDI block map will hold an offset to the actual block if
cd9d16
the block is allocated, or one of two specially-interpreted values if
cd9d16
not allocated. Using VirtualBox terminology, value VDI_IMAGE_BLOCK_FREE
cd9d16
(0xffffffff) represents a never-allocated block (semantically arbitrary
cd9d16
content).  VDI_IMAGE_BLOCK_ZERO (0xfffffffe) represents a "discarded"
cd9d16
block (semantically zero-filled).  block/vdi knows only about
cd9d16
VDI_IMAGE_BLOCK_FREE.  Teach it about VDI_IMAGE_BLOCK_ZERO.
cd9d16
cd9d16
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
cd9d16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
cd9d16
(cherry picked from commit c794b4e0fd9ef8d72b068614dcdb2418c105d5cc)
cd9d16
cd9d16
Signed-off-by: Bruce Rogers <brogers@suse.com>
cd9d16
Signed-off-by: Andreas Färber <afaerber@suse.de>
cd9d16
---
cd9d16
 block/vdi.c | 23 ++++++++++++++---------
cd9d16
 1 file changed, 14 insertions(+), 9 deletions(-)
cd9d16
cd9d16
diff --git a/block/vdi.c b/block/vdi.c
cd9d16
index 261cf9b..1be0cdc 100644
cd9d16
--- a/block/vdi.c
cd9d16
+++ b/block/vdi.c
cd9d16
@@ -114,8 +114,13 @@ void uuid_unparse(const uuid_t uu, char *out);
cd9d16
  */
cd9d16
 #define VDI_TEXT "<<< QEMU VM Virtual Disk Image >>>\n"
cd9d16
 
cd9d16
-/* Unallocated blocks use this index (no need to convert endianness). */
cd9d16
-#define VDI_UNALLOCATED UINT32_MAX
cd9d16
+/* A never-allocated block; semantically arbitrary content. */
cd9d16
+#define VDI_UNALLOCATED 0xffffffffU
cd9d16
+
cd9d16
+/* A discarded (no longer allocated) block; semantically zero-filled. */
cd9d16
+#define VDI_DISCARDED   0xfffffffeU
cd9d16
+
cd9d16
+#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
cd9d16
 
cd9d16
 #if !defined(CONFIG_UUID)
cd9d16
 void uuid_generate(uuid_t out)
cd9d16
@@ -307,10 +312,10 @@ static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res)
cd9d16
     /* Check block map and value of blocks_allocated. */
cd9d16
     for (block = 0; block < s->header.blocks_in_image; block++) {
cd9d16
         uint32_t bmap_entry = le32_to_cpu(s->bmap[block]);
cd9d16
-        if (bmap_entry != VDI_UNALLOCATED) {
cd9d16
+        if (VDI_IS_ALLOCATED(bmap_entry)) {
cd9d16
             if (bmap_entry < s->header.blocks_in_image) {
cd9d16
                 blocks_allocated++;
cd9d16
-                if (bmap[bmap_entry] == VDI_UNALLOCATED) {
cd9d16
+                if (!VDI_IS_ALLOCATED(bmap[bmap_entry])) {
cd9d16
                     bmap[bmap_entry] = bmap_entry;
cd9d16
                 } else {
cd9d16
                     fprintf(stderr, "ERROR: block index %" PRIu32
cd9d16
@@ -472,7 +477,7 @@ static int vdi_is_allocated(BlockDriverState *bs, int64_t sector_num,
cd9d16
         n_sectors = nb_sectors;
cd9d16
     }
cd9d16
     *pnum = n_sectors;
cd9d16
-    return bmap_entry != VDI_UNALLOCATED;
cd9d16
+    return VDI_IS_ALLOCATED(bmap_entry);
cd9d16
 }
cd9d16
 
cd9d16
 static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
cd9d16
@@ -603,7 +608,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
cd9d16
     /* prepare next AIO request */
cd9d16
     acb->n_sectors = n_sectors;
cd9d16
     bmap_entry = le32_to_cpu(s->bmap[block_index]);
cd9d16
-    if (bmap_entry == VDI_UNALLOCATED) {
cd9d16
+    if (!VDI_IS_ALLOCATED(bmap_entry)) {
cd9d16
         /* Block not allocated, return zeros, no need to wait. */
cd9d16
         memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
cd9d16
         ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
cd9d16
@@ -685,7 +690,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
cd9d16
         if (acb->header_modified) {
cd9d16
             VdiHeader *header = acb->block_buffer;
cd9d16
             logout("now writing modified header\n");
cd9d16
-            assert(acb->bmap_first != VDI_UNALLOCATED);
cd9d16
+            assert(VDI_IS_ALLOCATED(acb->bmap_first));
cd9d16
             *header = s->header;
cd9d16
             vdi_header_to_le(header);
cd9d16
             acb->header_modified = 0;
cd9d16
@@ -699,7 +704,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
cd9d16
                 goto done;
cd9d16
             }
cd9d16
             return;
cd9d16
-        } else if (acb->bmap_first != VDI_UNALLOCATED) {
cd9d16
+        } else if (VDI_IS_ALLOCATED(acb->bmap_first)) {
cd9d16
             /* One or more new blocks were allocated. */
cd9d16
             uint64_t offset;
cd9d16
             uint32_t bmap_first;
cd9d16
@@ -749,7 +754,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
cd9d16
     /* prepare next AIO request */
cd9d16
     acb->n_sectors = n_sectors;
cd9d16
     bmap_entry = le32_to_cpu(s->bmap[block_index]);
cd9d16
-    if (bmap_entry == VDI_UNALLOCATED) {
cd9d16
+    if (!VDI_IS_ALLOCATED(bmap_entry)) {
cd9d16
         /* Allocate new block and write to it. */
cd9d16
         uint64_t offset;
cd9d16
         uint8_t *block;
cd9d16
-- 
cd9d16
1.7.11.2
cd9d16