Index: /trunk/include/VBox/scsi.h
===================================================================
--- /trunk/include/VBox/scsi.h	(revision 15814)
+++ /trunk/include/VBox/scsi.h	(revision 15815)
@@ -32,4 +32,6 @@
 
 #include <iprt/assert.h>
+
+#define SCSI_MAX_BUFFER_SIZE (100 * _1K)
 
 
Index: /trunk/src/VBox/Devices/Storage/DevATA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevATA.cpp	(revision 15814)
+++ /trunk/src/VBox/Devices/Storage/DevATA.cpp	(revision 15815)
@@ -1789,5 +1789,5 @@
 
     if (pProf) { STAM_PROFILE_ADV_START(pProf, b); }
-    if (cbTransfer > 100 * _1K)
+    if (cbTransfer > SCSI_MAX_BUFFER_SIZE)
     {
         /* Linux accepts commands with up to 100KB of data, but expects
@@ -1836,6 +1836,6 @@
         for (uint32_t i = cSectors; i > 0; i -= cReqSectors)
         {
-            if (i * s->cbATAPISector > 100 * _1K)
-                cReqSectors = (100 * _1K) / s->cbATAPISector;
+            if (i * s->cbATAPISector > SCSI_MAX_BUFFER_SIZE)
+                cReqSectors = SCSI_MAX_BUFFER_SIZE / s->cbATAPISector;
             else
                 cReqSectors = i;
Index: /trunk/src/VBox/Devices/Storage/DrvHostBase.h
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvHostBase.h	(revision 15814)
+++ /trunk/src/VBox/Devices/Storage/DrvHostBase.h	(revision 15815)
@@ -131,4 +131,10 @@
 #endif
 
+#ifdef RT_OS_LINUX
+    /** Double buffer required for ioctl with the Linux kernel as long as we use
+     * remap_pfn_range() instead of vm_insert_page(). */
+    void                    *pbDoubleBuffer;
+#endif
+
 
     /**
Index: /trunk/src/VBox/Devices/Storage/DrvHostDVD.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvHostDVD.cpp	(revision 15814)
+++ /trunk/src/VBox/Devices/Storage/DrvHostDVD.cpp	(revision 15815)
@@ -56,4 +56,5 @@
 # include <errno.h>
 # include <limits.h>
+# include <iprt/mem.h>
 # define USE_MEDIA_POLLING
 
@@ -430,4 +431,5 @@
         case PDMBLOCKTXDIR_FROM_DEVICE:
             Assert(*pcbBuf != 0);
+            Assert(*pcbBuf <= SCSI_MAX_BUFFER_SIZE);
             /* Make sure that the buffer is clear for commands reading
              * data. The actually received data may be shorter than what
@@ -437,9 +439,11 @@
              * security problems inside the guest OS, if users can issue
              * commands to the CDROM device. */
-            memset(pvBuf, '\0', *pcbBuf);
+            memset(pThis->pbDoubleBuffer, '\0', *pcbBuf);
             direction = CGC_DATA_READ;
             break;
         case PDMBLOCKTXDIR_TO_DEVICE:
             Assert(*pcbBuf != 0);
+            Assert(*pcbBuf <= SCSI_MAX_BUFFER_SIZE);
+            memcpy(pThis->pbDoubleBuffer, pvBuf, *pcbBuf);
             direction = CGC_DATA_WRITE;
             break;
@@ -450,5 +454,5 @@
     memset(&cgc, '\0', sizeof(cgc));
     memcpy(cgc.cmd, pbCmd, CDROM_PACKET_SIZE);
-    cgc.buffer = (unsigned char *)pvBuf;
+    cgc.buffer = (unsigned char *)pThis->pbDoubleBuffer;
     cgc.buflen = *pcbBuf;
     cgc.stat = 0;
@@ -472,4 +476,12 @@
             Log2(("%s: error status %d, rc=%Rrc\n", __FUNCTION__, cgc.stat, rc));
         }
+    }
+    switch (enmTxDir)
+    {
+        case PDMBLOCKTXDIR_FROM_DEVICE:
+            memcpy(pvBuf, pThis->pbDoubleBuffer, *pcbBuf);
+            break;
+        default:
+            ;
     }
     Log2(("%s: after ioctl: cgc.buflen=%d txlen=%d\n", __FUNCTION__, cgc.buflen, *pcbBuf));
@@ -722,4 +734,9 @@
          * Override stuff.
          */
+#ifdef RT_OS_LINUX
+        pThis->pbDoubleBuffer = RTMemAlloc(SCSI_MAX_BUFFER_SIZE);
+        if (!pThis->pbDoubleBuffer)
+            return VERR_NO_MEMORY;
+#endif
 
 #ifndef RT_OS_L4 /* Passthrough is not supported on L4 yet */
@@ -776,4 +793,18 @@
 }
 
+/** @copydoc FNPDMDRVDESTRUCT */
+DECLCALLBACK(void) drvHostDvdDestruct(PPDMDRVINS pDrvIns)
+{
+#ifdef RT_OS_LINUX
+    PDRVHOSTBASE pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTBASE);
+
+    if (pThis->pbDoubleBuffer)
+    {
+        RTMemFree(pThis->pbDoubleBuffer);
+        pThis->pbDoubleBuffer = NULL;
+    }
+#endif
+    return DRVHostBaseDestruct(pDrvIns);
+}
 
 /**
@@ -799,5 +830,5 @@
     drvHostDvdConstruct,
     /* pfnDestruct */
-    DRVHostBaseDestruct,
+    drvHostDvdDestruct,
     /* pfnIOCtl */
     NULL,
