Index: /trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VBoxHDD.cpp	(revision 30312)
+++ /trunk/src/VBox/Devices/Storage/VBoxHDD.cpp	(revision 30313)
@@ -534,8 +534,10 @@
  */
 static int vdReadHelper(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride,
-                        uint64_t uOffset, void *pvBuf, size_t cbRead)
+                        uint64_t uOffset, void *pvBuf, size_t cbRead, bool fHandleFreeBlocks)
 {
     int rc;
     size_t cbThisRead;
+    bool fAllFree = true;
+    size_t cbBufClear = 0;
 
     /* Loop until all read. */
@@ -570,6 +572,21 @@
         if (rc == VERR_VD_BLOCK_FREE)
         {
-            memset(pvBuf, '\0', cbThisRead);
+            /* Fill the free space with 0 if we are told to do so. */
+            if (fHandleFreeBlocks)
+                memset(pvBuf, '\0', cbThisRead);
+            else
+                cbBufClear += cbThisRead;
+
             rc = VINF_SUCCESS;
+        }
+        else if (RT_SUCCESS(rc))
+        {
+            /* First not free block, fill the space before with 0. */
+            if (!fHandleFreeBlocks)
+            {
+                memset((char *)pvBuf - cbBufClear, '\0', cbBufClear);
+                cbBufClear = 0;
+                fAllFree = false;
+            }
         }
 
@@ -579,5 +596,5 @@
     } while (cbRead != 0 && RT_SUCCESS(rc));
 
-    return rc;
+    return (!fHandleFreeBlocks && fAllFree) ? VERR_VD_BLOCK_FREE : rc;
 }
 
@@ -891,5 +908,5 @@
     PVDPARENTSTATEDESC pParentState = (PVDPARENTSTATEDESC)pvUser;
     return vdReadHelper(pParentState->pDisk, pParentState->pImage, NULL, uOffset,
-                        pvBuf, cbRead);
+                        pvBuf, cbRead, true);
 }
 
@@ -952,5 +969,5 @@
     {
         rc = vdReadHelper(pDisk, pImage, pImageParentOverride,
-                          uOffset - cbPreRead, pvTmp, cbPreRead);
+                          uOffset - cbPreRead, pvTmp, cbPreRead, true);
         if (RT_FAILURE(rc))
             return rc;
@@ -989,5 +1006,5 @@
                               uOffset + cbThisWrite + cbWriteCopy,
                               (char *)pvTmp + cbPreRead + cbThisWrite + cbWriteCopy,
-                              cbReadImage);
+                              cbReadImage, true);
         if (RT_FAILURE(rc))
             return rc;
@@ -1049,5 +1066,5 @@
      * be modified by the write or not. */
     rc = vdReadHelper(pDisk, pImage, pImageParentOverride, uOffset - cbPreRead, pvTmp,
-                      cbPreRead + cbThisWrite + cbPostRead - cbFill);
+                      cbPreRead + cbThisWrite + cbPostRead - cbFill, true);
     if (RT_FAILURE(rc))
         return rc;
@@ -4076,4 +4093,8 @@
         }
 
+        /* Whether we can take the optimized copy path (false) or not.
+         * Don't optimize if the image existed or if it is a child image. */
+        bool fRegularRead = (pszFilename == NULL) || (cImagesTo > 0);
+
         /* Copy the data. */
         uint64_t uOffset = 0;
@@ -4094,6 +4115,6 @@
 
             rc = vdReadHelper(pDiskFrom, pImageFrom, NULL, uOffset, pvBuf,
-                              cbThisRead);
-            if (RT_FAILURE(rc))
+                              cbThisRead, fRegularRead);
+            if (RT_FAILURE(rc) && rc != VERR_VD_BLOCK_FREE)
                 break;
 
@@ -4102,16 +4123,19 @@
             fLockReadFrom = false;
 
-            rc2 = vdThreadStartWrite(pDiskTo);
-            AssertRC(rc2);
-            fLockWriteTo = true;
-
-            rc = vdWriteHelper(pDiskTo, pImageTo, NULL, uOffset, pvBuf,
-                               cbThisRead);
-            if (RT_FAILURE(rc))
-                break;
-
-            rc2 = vdThreadFinishWrite(pDiskTo);
-            AssertRC(rc2);
-            fLockWriteTo = false;
+            if (rc != VERR_VD_BLOCK_FREE)
+            {
+                rc2 = vdThreadStartWrite(pDiskTo);
+                AssertRC(rc2);
+                fLockWriteTo = true;
+
+                rc = vdWriteHelper(pDiskTo, pImageTo, NULL, uOffset, pvBuf,
+                                   cbThisRead);
+                if (RT_FAILURE(rc))
+                    break;
+
+                rc2 = vdThreadFinishWrite(pDiskTo);
+                AssertRC(rc2);
+                fLockWriteTo = false;
+            }
 
             uOffset += cbThisRead;
@@ -4531,5 +4555,5 @@
         AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED);
 
-        rc = vdReadHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbRead);
+        rc = vdReadHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbRead, true);
     } while (0);
 
