Index: /trunk/include/VBox/VBoxHDD.h
===================================================================
--- /trunk/include/VBox/VBoxHDD.h	(revision 31179)
+++ /trunk/include/VBox/VBoxHDD.h	(revision 31180)
@@ -169,9 +169,11 @@
  *  Only available if VD_CAP_ASYNC_IO is set
  *  Check with VDIsAsynchonousIoSupported wether
- *  asynchronous I/O is really supported for this file.
- */
+ *  asynchronous I/O is really supported for this file.  */
 #define VD_OPEN_FLAGS_ASYNC_IO      RT_BIT(4)
+/** Allow sharing of the image for writable images. May be ignored if the
+ * format backend doesn't support this type of concurrent access. */
+#define VD_OPEN_FLAGS_SHAREABLE     RT_BIT(5)
 /** Mask of valid flags. */
-#define VD_OPEN_FLAGS_MASK          (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO)
+#define VD_OPEN_FLAGS_MASK          (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)
 /** @}*/
 
Index: /trunk/src/VBox/Devices/Storage/DrvVD.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 31179)
+++ /trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 31180)
@@ -161,4 +161,6 @@
     /** Pointer to the list of data we need to keep per image. */
     PVBOXIMAGE               pImages;
+    /** Flag whether the media should allow concurrent open for writing. */
+    bool                fShareable;
     /** Flag whether a merge operation has been set up. */
     bool                fMergePending;
@@ -342,8 +344,13 @@
             if (RT_SUCCESS(rc))
             {
-                rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation,
-                                                         uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
-                                                         ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
-                                                         : PDMACEP_FILE_FLAGS_CACHING,
+                uint32_t fFlags =    uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
+                                   ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
+                                   : 0;
+                if (pThis->fShareable)
+                    fFlags |= PDMACEP_FILE_FLAGS_DONT_LOCK;
+                else
+                    fFlags |= PDMACEP_FILE_FLAGS_CACHING;
+                rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint,
+                                                         pszLocation, fFlags,
                                                          pStorageBackend->pTemplate);
                 if (RT_SUCCESS(rc))
@@ -1634,4 +1641,5 @@
     pThis->pDisk                        = NULL;
     pThis->fAsyncIOSupported            = false;
+    pThis->fShareable                   = false;
     pThis->fMergePending                = false;
     pThis->MergeCompleteMutex           = NIL_RTSEMFASTMUTEX;
@@ -1702,5 +1710,5 @@
             fValid = CFGMR3AreValuesValid(pCurNode,
                                           "Format\0Path\0"
-                                          "ReadOnly\0MaybeReadOnly\0TempReadOnly\0HonorZeroWrites\0"
+                                          "ReadOnly\0MaybeReadOnly\0TempReadOnly\0Shareable\0HonorZeroWrites\0"
                                           "HostIPStack\0UseNewIo\0"
                                           "SetupMerge\0MergeSource\0MergeTarget\0");
@@ -1767,4 +1775,13 @@
                 break;
             }
+
+            rc = CFGMR3QueryBoolDef(pCurNode, "Shareable", &pThis->fShareable, false);
+            if (RT_FAILURE(rc))
+            {
+                rc = PDMDRV_SET_ERROR(pDrvIns, rc,
+                                      N_("DrvVD: Configuration error: Querying \"Shareable\" as boolean failed"));
+                break;
+            }
+
             rc = CFGMR3QueryBoolDef(pCurNode, "UseNewIo", &fUseNewIo, false);
             if (RT_FAILURE(rc))
@@ -2008,4 +2025,6 @@
         if (pThis->fAsyncIOSupported)
             uOpenFlags |= VD_OPEN_FLAGS_ASYNC_IO;
+        if (pThis->fShareable)
+            uOpenFlags |= VD_OPEN_FLAGS_SHAREABLE;
 
         /* Try to open backend in async I/O mode first. */
Index: /trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp	(revision 31179)
+++ /trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp	(revision 31180)
@@ -79,13 +79,15 @@
 
 
-static int vdiFileOpen(PVDIIMAGEDESC pImage, bool fReadonly, bool fCreate)
+static int vdiFileOpen(PVDIIMAGEDESC pImage, bool fReadonly, bool fShareable,
+                       bool fCreate)
 {
     int rc = VINF_SUCCESS;
 
-    AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly whilebeing created\n"));
+    AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
 
 #ifndef VBOX_WITH_NEW_IO_CODE
-    uint32_t fOpen = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
-                               : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
+    uint32_t fDeny = fReadonly | fShareable ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE;
+    uint32_t fOpen = fReadonly ? RTFILE_O_READ : RTFILE_O_READWRITE;
+    fOpen |= fDeny;
 
     if (fCreate)
@@ -514,6 +516,7 @@
                           PCPDMMEDIAGEOMETRY pPCHSGeometry,
                           PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
-                          PFNVDPROGRESS pfnProgress, void *pvUser,
-                          unsigned uPercentStart, unsigned uPercentSpan)
+                          unsigned uOpenFlags, PFNVDPROGRESS pfnProgress,
+                          void *pvUser, unsigned uPercentStart,
+                          unsigned uPercentSpan)
 {
     int rc;
@@ -580,5 +583,7 @@
 
     /* Create image file. */
-    rc = vdiFileOpen(pImage, false /* fReadonly */, true /* fCreate */);
+    rc = vdiFileOpen(pImage, false /* fReadonly */,
+                     !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),
+                     true /* fCreate */);
     if (RT_FAILURE(rc))
     {
@@ -733,5 +738,8 @@
      * Open the image.
      */
-    rc = vdiFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false /* fCreate */);
+    rc = vdiFileOpen(pImage,
+                     !!(uOpenFlags & VD_OPEN_FLAGS_READONLY),
+                     !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),
+                     false /* fCreate */);
     if (RT_FAILURE(rc))
     {
@@ -1159,5 +1167,5 @@
 
     rc = vdiCreateImage(pImage, cbSize, uImageFlags, pszComment,
-                        pPCHSGeometry, pLCHSGeometry, pUuid,
+                        pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags,
                         pfnProgress, pvUser, uPercentStart, uPercentSpan);
     if (RT_SUCCESS(rc))
Index: /trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp	(revision 31179)
+++ /trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp	(revision 31180)
@@ -261,5 +261,6 @@
 static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset);
 
-static int vhdFileOpen(PVHDIMAGE pImage, bool fReadonly, bool fCreate)
+static int vhdFileOpen(PVHDIMAGE pImage, bool fReadonly, bool fShareable,
+                       bool fCreate)
 {
     int rc = VINF_SUCCESS;
@@ -268,6 +269,7 @@
 
 #ifndef VBOX_WITH_NEW_IO_CODE
-    uint32_t fOpen = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
-                               : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
+    uint32_t fDeny = fReadonly | fShareable ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE;
+    uint32_t fOpen = fReadonly ? RTFILE_O_READ : RTFILE_O_READWRITE;
+    fOpen |= fDeny;
 
     if (fCreate)
@@ -729,5 +731,6 @@
      * Open the image.
      */
-    int rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
+    int rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY),
+                         !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE), false);
     if (RT_FAILURE(rc))
     {
@@ -1097,5 +1100,6 @@
     vhdFileClose(pImage);
     pImage->uOpenFlags = uOpenFlags;
-    rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
+    rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY),
+                     !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE), false);
 
 out:
@@ -1956,5 +1960,7 @@
         pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
 
-    rc = vhdFileOpen(pImage, false /* fReadonly */, true /* fCreate */);
+    rc = vhdFileOpen(pImage, false /* fReadonly */,
+                     !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),
+                     true /* fCreate */);
     if (RT_FAILURE(rc))
         return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot create image '%s'"), pImage->pszFilename);
Index: /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 31179)
+++ /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 31180)
@@ -3157,4 +3157,19 @@
 
 /**
+ * Internal: Translate the VBoxHDD open flags to RTFile open flags.
+ */
+static uint32_t vmdkFileOpenFlags(unsigned uOpenFlags)
+{
+    uint32_t fDeny =   uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE)
+                     ? RTFILE_O_DENY_NONE
+                     : RTFILE_O_DENY_WRITE;
+    uint32_t fOpen =   uOpenFlags & VD_OPEN_FLAGS_READONLY
+                     ? RTFILE_O_READ
+                     : RTFILE_O_READWRITE;
+    fOpen |= RTFILE_O_OPEN | fDeny;
+    return fOpen;
+}
+
+/**
  * Internal: Open an image, constructing all necessary data structures.
  */
@@ -3184,8 +3199,7 @@
      * file were no data is stored.
      */
+
     rc = vmdkFileOpen(pImage, &pFile, pImage->pszFilename,
-                      uOpenFlags & VD_OPEN_FLAGS_READONLY
-                       ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
-                       : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false);
+                      vmdkFileOpenFlags(uOpenFlags), false);
     if (RT_FAILURE(rc))
     {
@@ -3402,7 +3416,5 @@
                 case VMDKETYPE_HOSTED_SPARSE:
                     rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
-                                      uOpenFlags & VD_OPEN_FLAGS_READONLY
-                                        ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
-                                        : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false);
+                                      vmdkFileOpenFlags(uOpenFlags), false);
                     if (RT_FAILURE(rc))
                     {
@@ -3429,7 +3441,5 @@
                 case VMDKETYPE_FLAT:
                     rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
-                                      uOpenFlags & VD_OPEN_FLAGS_READONLY
-                                        ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
-                                        : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, true);
+                                      vmdkFileOpenFlags(uOpenFlags), true);
                     if (RT_FAILURE(rc))
                     {
@@ -3512,4 +3522,17 @@
 
 /**
+ * Internal: Translate the VBoxHDD open flags to RTFile open/create flags.
+ */
+static uint32_t vmdkFileCreateFlags(unsigned uOpenFlags)
+{
+    uint32_t fDeny =   uOpenFlags & VD_OPEN_FLAGS_SHAREABLE
+                     ? RTFILE_O_DENY_NONE
+                     : RTFILE_O_DENY_WRITE;
+    uint32_t fOpen = RTFILE_O_READWRITE | RTFILE_O_NOT_CONTENT_INDEXED;
+    fOpen |= RTFILE_O_CREATE | fDeny;
+    return fOpen;
+}
+
+/**
  * Internal: create VMDK images for raw disk/partition access.
  */
@@ -3530,6 +3553,5 @@
         /* Create raw disk descriptor file. */
         rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
-                          RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED,
-                          false);
+                          vmdkFileCreateFlags(pImage->uOpenFlags), false);
         if (RT_FAILURE(rc))
             return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
@@ -3554,5 +3576,6 @@
         /* Open flat image, the raw disk. */
         rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
-                          RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false);
+                          vmdkFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY),
+                          false);
         if (RT_FAILURE(rc))
             return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname);
@@ -3590,6 +3613,5 @@
         /* Create raw partition descriptor file. */
         rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
-                          RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED,
-                          false);
+                          vmdkFileCreateFlags(pImage->uOpenFlags), false);
         if (RT_FAILURE(rc))
             return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
@@ -3665,5 +3687,5 @@
                 /* Create partition table flat image. */
                 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
-                                  RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED,
+                                  vmdkFileCreateFlags(pImage->uOpenFlags),
                                   false);
                 if (RT_FAILURE(rc))
@@ -3700,5 +3722,5 @@
                     /* Open flat image, the raw partition. */
                     rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
-                                      RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE,
+                                      vmdkFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY),
                                       false);
                     if (RT_FAILURE(rc))
@@ -3773,6 +3795,5 @@
     {
         rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
-                          RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED,
-                          false);
+                          vmdkFileCreateFlags(pImage->uOpenFlags), false);
         if (RT_FAILURE(rc))
             return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename);
@@ -3843,6 +3864,5 @@
         /* Create file for extent. */
         rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
-                          RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED,
-                          false);
+                          vmdkFileCreateFlags(pImage->uOpenFlags), false);
         if (RT_FAILURE(rc))
             return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
@@ -5521,5 +5541,6 @@
         PVMDKFILE pFile;
         rrc = vmdkFileOpen(pImage, &pFile, pszOldDescName,
-            RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false);
+                           vmdkFileOpenFlags(VD_OPEN_FLAGS_NORMAL),
+                           false);
         AssertRC(rrc);
         if (fEmbeddedDesc)
Index: /trunk/src/VBox/Main/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 31179)
+++ /trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 31180)
@@ -2813,7 +2813,9 @@
 
         BOOL fHostDrive = FALSE;
+        MediumType_T mediumType  = MediumType_Normal;
         if (pMedium)
         {
             hrc = pMedium->COMGETTER(HostDrive)(&fHostDrive);                               H();
+            hrc = pMedium->COMGETTER(Type)(&mediumType);                                    H();
         }
 
@@ -2945,4 +2947,12 @@
                 {
                     InsertConfigInteger(pCfg, "TempReadOnly", 1);
+                }
+
+                /* Flag for opening the medium for sharing between VMs. This
+                 * is done at the moment only for the first (and only) medium
+                 * in the chain, as shared media can have no diffs. */
+                if (mediumType == MediumType_Shareable)
+                {
+                    InsertConfigInteger(pCfg, "Shareable", 1);
                 }
 
Index: /trunk/src/VBox/Main/MediumImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MediumImpl.cpp	(revision 31179)
+++ /trunk/src/VBox/Main/MediumImpl.cpp	(revision 31180)
@@ -3482,5 +3482,5 @@
      * location? */
     bool isImport = m->id.isEmpty();
-    unsigned flags = VD_OPEN_FLAGS_INFO;
+    unsigned uOpenFlags = VD_OPEN_FLAGS_INFO;
 
     /* Note that we don't use VD_OPEN_FLAGS_READONLY when opening new
@@ -3492,8 +3492,12 @@
          || !isImport
        )
-        flags |= VD_OPEN_FLAGS_READONLY;
+        uOpenFlags |= VD_OPEN_FLAGS_READONLY;
+
+    /* Open shareable medium with the appropriate flags */
+    if (m->type == MediumType_Shareable)
+        uOpenFlags |= VD_OPEN_FLAGS_SHAREABLE;
 
     /* Lock the medium, which makes the behavior much more consistent */
-    if (flags & VD_OPEN_FLAGS_READONLY)
+    if (uOpenFlags & (VD_OPEN_FLAGS_READONLY || VD_OPEN_FLAGS_SHAREABLE))
         rc = LockRead(NULL);
     else
@@ -3542,5 +3546,5 @@
                          format.c_str(),
                          location.c_str(),
-                         flags,
+                         uOpenFlags,
                          m->vdDiskIfaces);
             if (RT_FAILURE(vrc))
@@ -3740,5 +3744,5 @@
         m->preLockState = MediumState_Inaccessible;
 
-    if (flags & VD_OPEN_FLAGS_READONLY)
+    if (uOpenFlags & (VD_OPEN_FLAGS_READONLY || VD_OPEN_FLAGS_SHAREABLE))
         rc = UnlockRead(NULL);
     else
@@ -5713,9 +5717,11 @@
                        || pMedium->m->state == MediumState_Deleting);
 
-                unsigned uOpenFlags = 0;
+                unsigned uOpenFlags = VD_OPEN_FLAGS_NORMAL;
 
                 if (   pMedium->m->state == MediumState_LockedRead
                     || pMedium->m->state == MediumState_Deleting)
                     uOpenFlags = VD_OPEN_FLAGS_READONLY;
+                if (pMedium->m->type == MediumType_Shareable)
+                    uOpenFlags |= VD_OPEN_FLAGS_SHAREABLE;
 
                 /* Open the medium */
@@ -6058,9 +6064,15 @@
                             || pMedium->m->state == MediumState_LockedWrite);
 
+                    unsigned uOpenFlags = VD_OPEN_FLAGS_NORMAL;
+                    if (pMedium->m->state != MediumState_LockedWrite)
+                        uOpenFlags = VD_OPEN_FLAGS_READONLY;
+                    if (pMedium->m->type == MediumType_Shareable)
+                        uOpenFlags |= VD_OPEN_FLAGS_SHAREABLE;
+
                     /* Open all media in appropriate mode. */
                     vrc = VDOpen(targetHdd,
                                  pMedium->m->strFormat.c_str(),
                                  pMedium->m->strLocationFull.c_str(),
-                                 (pMedium->m->state == MediumState_LockedWrite) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
+                                 uOpenFlags,
                                  pMedium->m->vdDiskIfaces);
                     if (RT_FAILURE(vrc))
@@ -6436,5 +6448,7 @@
                     Assert(pMedium->m->state == MediumState_LockedRead);
 
-                /** Open all media but last in read-only mode. */
+                /* Open all media but last in read-only mode. Do not handle
+                 * shareable media, as compaction and sharing are mutually
+                 * exclusive. */
                 vrc = VDOpen(hdd,
                              pMedium->m->strFormat.c_str(),
