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