Changeset 32882 in vbox
- Timestamp:
- Oct 4, 2010 9:19:15 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r32642 r32882 314 314 /** Starting sector of the decompressed grain buffer. */ 315 315 uint32_t uGrainSector; 316 /** Size of compressed grain buffer for streamOptimized extents. */ 317 size_t cbCompGrain; 318 /** Compressed grain buffer for streamOptimized extents, with marker. */ 319 void *pvCompGrain; 316 320 /** Decompressed grain buffer for streamOptimized extents. */ 317 321 void *pvGrain; … … 474 478 /* Image this operation relates to. */ 475 479 PVMDKIMAGE pImage; 476 /* File where the data is stored. */477 PVMDKFILE pFile;478 /* Total size of the data to read. */479 size_t cbSize;480 /* Offset in the file to read. */481 uint64_t uFileOffset;482 480 /* Current read position. */ 483 481 ssize_t iOffset; 482 /* Size of the compressed grain buffer (available data). */ 483 size_t cbCompGrain; 484 /* Pointer to the compressed grain buffer. */ 485 void *pvCompGrain; 484 486 } VMDKINFLATESTATE; 485 487 … … 489 491 /* Image this operation relates to. */ 490 492 PVMDKIMAGE pImage; 491 /* File where the data is to be stored. */492 PVMDKFILE pFile;493 /* Offset in the file to write at. */494 uint64_t uFileOffset;495 493 /* Current write position. */ 496 494 ssize_t iOffset; 495 /* Size of the compressed grain buffer. */ 496 size_t cbCompGrain; 497 /* Pointer to the compressed grain buffer. */ 498 void *pvCompGrain; 497 499 } VMDKDEFLATESTATE; 498 500 … … 851 853 { 852 854 VMDKINFLATESTATE *pInflateState = (VMDKINFLATESTATE *)pvUser; 855 size_t cbInjected = 0; 853 856 854 857 Assert(cbBuf); … … 856 859 { 857 860 *(uint8_t *)pvBuf = RTZIPTYPE_ZLIB; 861 pvBuf = (uint8_t *)pvBuf + 1; 862 cbBuf--; 863 cbInjected = 1; 864 pInflateState->iOffset = RT_OFFSETOF(VMDKMARKER, uType); 865 } 866 if (!cbBuf) 867 { 858 868 if (pcbBuf) 859 *pcbBuf = 1; 860 pInflateState->iOffset = 0; 869 *pcbBuf = cbInjected; 861 870 return VINF_SUCCESS; 862 871 } 863 cbBuf = RT_MIN(cbBuf, pInflateState->cbSize); 864 int rc = vmdkFileReadSync(pInflateState->pImage, pInflateState->pFile, 865 pInflateState->uFileOffset, pvBuf, cbBuf, NULL); 866 if (RT_FAILURE(rc)) 867 return rc; 868 pInflateState->uFileOffset += cbBuf; 872 cbBuf = RT_MIN(cbBuf, pInflateState->cbCompGrain - pInflateState->iOffset); 873 memcpy(pvBuf, 874 (uint8_t *)pInflateState->pvCompGrain + pInflateState->iOffset, 875 cbBuf); 869 876 pInflateState->iOffset += cbBuf; 870 pInflateState->cbSize -= cbBuf;871 877 Assert(pcbBuf); 872 *pcbBuf = cbBuf ;878 *pcbBuf = cbBuf + cbInjected; 873 879 return VINF_SUCCESS; 874 880 } … … 878 884 * distinguishing between async and normal operation 879 885 */ 880 DECLINLINE(int) vmdkFileInflateSync(PVMDKIMAGE pImage, PVMDK FILE pVmdkFile,886 DECLINLINE(int) vmdkFileInflateSync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 881 887 uint64_t uOffset, void *pvBuf, 882 size_t cbToRead, u nsigned uMarker,883 uint 64_t *puLBA, uint32_t *pcbMarkerData)884 { 885 if (p VmdkFile->fAsyncIO)888 size_t cbToRead, uint64_t *puLBA, 889 uint32_t *pcbMarkerData) 890 { 891 if (pExtent->pFile->fAsyncIO) 886 892 { 887 893 AssertMsgFailed(("TODO\n")); … … 892 898 int rc; 893 899 PRTZIPDECOMP pZip = NULL; 894 VMDKMARKER Marker; 895 uint64_t uCompOffset, cbComp; 896 VMDKINFLATESTATE InflateState; 897 size_t cbActuallyRead; 898 size_t cbMarker = sizeof(Marker); 899 900 if (uMarker == VMDK_MARKER_IGNORE) 901 cbMarker -= sizeof(Marker.uType); 902 rc = vmdkFileReadSync(pImage, pVmdkFile, uOffset, &Marker, cbMarker, NULL); 900 VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain; 901 size_t cbCompSize, cbActuallyRead; 902 903 rc = vmdkFileReadSync(pImage, pExtent->pFile, uOffset, pMarker, 904 RT_OFFSETOF(VMDKMARKER, uType), NULL); 903 905 if (RT_FAILURE(rc)) 904 906 return rc; 905 Marker.uSector = RT_LE2H_U64(Marker.uSector); 906 Marker.cbSize = RT_LE2H_U32(Marker.cbSize); 907 if ( uMarker != VMDK_MARKER_IGNORE 908 && ( RT_LE2H_U32(Marker.uType) != uMarker 909 || Marker.cbSize != 0)) 907 cbCompSize = RT_LE2H_U32(pMarker->cbSize); 908 if (cbCompSize == 0) 909 { 910 AssertMsgFailed(("VMDK: corrupted marker\n")); 910 911 return VERR_VD_VMDK_INVALID_FORMAT; 911 if (Marker.cbSize != 0) 912 { 913 /* Compressed grain marker. Data follows immediately. */ 914 uCompOffset = uOffset + 12; 915 cbComp = Marker.cbSize; 916 if (puLBA) 917 *puLBA = Marker.uSector; 918 if (pcbMarkerData) 919 *pcbMarkerData = cbComp + 12; 920 } 921 else 922 { 923 Marker.uType = RT_LE2H_U32(Marker.uType); 924 AssertMsgFailed(("VMDK: unexpected marker type %u\n", Marker.uType)); 912 } 913 914 /* Sanity check - the expansion ratio should be much less than 2. */ 915 Assert(cbCompSize < 2 * cbToRead); 916 if (cbCompSize >= 2 * cbToRead) 925 917 return VERR_VD_VMDK_INVALID_FORMAT; 926 } 918 919 /* Compressed grain marker. Data follows immediately. */ 920 rc = vmdkFileReadSync(pImage, pExtent->pFile, 921 uOffset + RT_OFFSETOF(VMDKMARKER, uType), 922 (uint8_t *)pExtent->pvCompGrain 923 + RT_OFFSETOF(VMDKMARKER, uType), 924 RT_ALIGN_Z( cbCompSize 925 + RT_OFFSETOF(VMDKMARKER, uType), 926 512) 927 - RT_OFFSETOF(VMDKMARKER, uType), NULL); 928 929 if (puLBA) 930 *puLBA = RT_LE2H_U64(pMarker->uSector); 931 if (pcbMarkerData) 932 *pcbMarkerData = RT_ALIGN( cbCompSize 933 + RT_OFFSETOF(VMDKMARKER, uType), 934 512); 935 936 VMDKINFLATESTATE InflateState; 927 937 InflateState.pImage = pImage; 928 InflateState.pFile = pVmdkFile;929 InflateState.cbSize = cbComp;930 InflateState.uFileOffset = uCompOffset;931 938 InflateState.iOffset = -1; 932 /* Sanity check - the expansion ratio should be much less than 2. */ 933 Assert(cbComp < 2 * cbToRead); 934 if (cbComp >= 2 * cbToRead) 935 return VERR_VD_VMDK_INVALID_FORMAT; 939 InflateState.cbCompGrain = cbCompSize + RT_OFFSETOF(VMDKMARKER, uType); 940 InflateState.pvCompGrain = pExtent->pvCompGrain; 936 941 937 942 rc = RTZipDecompCreate(&pZip, &InflateState, vmdkFileInflateHelper); … … 957 962 pvBuf = (const uint8_t *)pvBuf + 1; 958 963 cbBuf--; 959 pDeflateState->iOffset = 0;964 pDeflateState->iOffset = RT_OFFSETOF(VMDKMARKER, uType); 960 965 } 961 966 if (!cbBuf) 962 967 return VINF_SUCCESS; 963 int rc = vmdkFileWriteSync(pDeflateState->pImage, pDeflateState->pFile, 964 pDeflateState->uFileOffset, pvBuf, cbBuf, NULL); 965 if (RT_FAILURE(rc)) 966 return rc; 967 pDeflateState->uFileOffset += cbBuf; 968 if (pDeflateState->iOffset + cbBuf > pDeflateState->cbCompGrain) 969 return VERR_BUFFER_OVERFLOW; 970 memcpy((uint8_t *)pDeflateState->pvCompGrain + pDeflateState->iOffset, 971 pvBuf, cbBuf); 968 972 pDeflateState->iOffset += cbBuf; 969 973 return VINF_SUCCESS; … … 974 978 * distinguishing between async and normal operation 975 979 */ 976 DECLINLINE(int) vmdkFileDeflateSync(PVMDKIMAGE pImage, PVMDK FILE pVmdkFile,980 DECLINLINE(int) vmdkFileDeflateSync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 977 981 uint64_t uOffset, const void *pvBuf, 978 size_t cbToWrite, u nsigned uMarker,979 uint 64_t uLBA, uint32_t *pcbMarkerData)980 { 981 if (p VmdkFile->fAsyncIO)982 size_t cbToWrite, uint64_t uLBA, 983 uint32_t *pcbMarkerData) 984 { 985 if (pExtent->pFile->fAsyncIO) 982 986 { 983 987 AssertMsgFailed(("TODO\n")); … … 988 992 int rc; 989 993 PRTZIPCOMP pZip = NULL; 990 VMDKMARKER Marker;991 uint64_t uCompOffset, cbDecomp;992 994 VMDKDEFLATESTATE DeflateState; 993 995 994 Marker.uSector = RT_H2LE_U64(uLBA);995 Marker.cbSize = RT_H2LE_U32((uint32_t)cbToWrite);996 if (uMarker == VMDK_MARKER_IGNORE)997 {998 /* Compressed grain marker. Data follows immediately. */999 uCompOffset = uOffset + 12;1000 cbDecomp = cbToWrite;1001 }1002 else1003 {1004 /* The other markers don't contain compressed data. */1005 return VERR_NOT_IMPLEMENTED;1006 }1007 996 DeflateState.pImage = pImage; 1008 DeflateState.pFile = pVmdkFile;1009 DeflateState.uFileOffset = uCompOffset;1010 997 DeflateState.iOffset = -1; 998 DeflateState.cbCompGrain = pExtent->cbCompGrain; 999 DeflateState.pvCompGrain = pExtent->pvCompGrain; 1011 1000 1012 1001 rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper, RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT); 1013 1002 if (RT_FAILURE(rc)) 1014 1003 return rc; 1015 rc = RTZipCompress(pZip, pvBuf, cb Decomp);1004 rc = RTZipCompress(pZip, pvBuf, cbToWrite); 1016 1005 if (RT_SUCCESS(rc)) 1017 1006 rc = RTZipCompFinish(pZip); … … 1019 1008 if (RT_SUCCESS(rc)) 1020 1009 { 1010 Assert( DeflateState.iOffset > 0 1011 && (size_t)DeflateState.iOffset <= DeflateState.cbCompGrain); 1012 1013 /* pad with zeroes to get to a full sector size */ 1014 uint32_t uSize = DeflateState.iOffset; 1015 if (uSize % 512) 1016 { 1017 uint32_t uSizeAlign = RT_ALIGN(uSize, 512); 1018 memset((uint8_t *)pExtent->pvCompGrain + uSize, '\0', 1019 uSizeAlign - uSize); 1020 uSize = uSizeAlign; 1021 } 1022 1021 1023 if (pcbMarkerData) 1022 *pcbMarkerData = 12 + DeflateState.iOffset; 1024 *pcbMarkerData = uSize; 1025 1026 /* Compressed grain marker. Data follows immediately. */ 1027 VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain; 1028 pMarker->uSector = RT_H2LE_U64(uLBA); 1029 pMarker->cbSize = RT_H2LE_U32( DeflateState.iOffset 1030 - RT_OFFSETOF(VMDKMARKER, uType)); 1031 rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOffset, pMarker, 1032 uSize, NULL); 1033 if (RT_FAILURE(rc)) 1034 return rc; 1035 1023 1036 /* Set the file size to remove old garbage in case the block is 1024 1037 * rewritten. Cannot cause data loss as the code calling this 1025 * guarantees that data gets only appended. */ 1026 Assert(DeflateState.uFileOffset > uCompOffset); 1027 1028 /* 1029 * Change the file size only if the size really changed, 1030 * because this is very expensive on some filesystems 1031 * like XFS. 1032 */ 1038 * guarantees that data gets only appended. Change the file size 1039 * only if the size really changed, because this is very expensive 1040 * on some filesystems such as XFS. */ 1033 1041 uint64_t cbOld; 1034 rc = vmdkFileGetSize(pImage, p VmdkFile, &cbOld);1042 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbOld); 1035 1043 if (RT_FAILURE(rc)) 1036 1044 return rc; 1037 1045 1038 if (cbOld != DeflateState.uFileOffset) 1039 rc = vmdkFileSetSize(pImage, pVmdkFile, DeflateState.uFileOffset); 1040 1041 if (uMarker == VMDK_MARKER_IGNORE) 1042 { 1043 /* Compressed grain marker. */ 1044 Marker.cbSize = RT_H2LE_U32(DeflateState.iOffset); 1045 rc = vmdkFileWriteSync(pImage, pVmdkFile, uOffset, &Marker, 12, NULL); 1046 if (RT_FAILURE(rc)) 1047 return rc; 1048 } 1049 else 1050 { 1051 /* The other markers don't contain compressed data. */ 1052 return VERR_NOT_IMPLEMENTED; 1053 } 1046 if (cbOld != uOffset + uSize) 1047 rc = vmdkFileSetSize(pImage, pExtent->pFile, uOffset + uSize); 1054 1048 } 1055 1049 return rc; … … 1349 1343 RTMemTmpFree(pTmpGT); 1350 1344 1351 /* streamOptimized extents need a grain decompress buffer. */ 1345 /* streamOptimized extents need a compressed grain buffer, which must 1346 * be big enough to hold uncompressible data (which needs ~8 bytes 1347 * more than the uncompressed data), the marker and padding. */ 1348 pExtent->cbCompGrain = RT_ALIGN_Z( VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain) 1349 + 8 + sizeof(VMDKMARKER), 512); 1350 pExtent->pvCompGrain = RTMemAlloc(pExtent->cbCompGrain); 1351 if (!pExtent->pvCompGrain) 1352 { 1353 rc = VERR_NO_MEMORY; 1354 goto out; 1355 } 1356 1357 /* streamOptimized extents need a decompressed grain buffer. */ 1352 1358 pExtent->pvGrain = RTMemAlloc(VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 1353 1359 if (!pExtent->pvGrain) … … 1361 1367 uint64_t uLBA = 0; 1362 1368 uint32_t cbMarker = 0; 1363 rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uLastGrainSector), 1364 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, &cbMarker); 1369 rc = vmdkFileInflateSync(pImage, pExtent, 1370 VMDK_SECTOR2BYTE(uLastGrainSector), 1371 pExtent->pvGrain, 1372 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 1373 &uLBA, &cbMarker); 1365 1374 if (RT_FAILURE(rc)) 1366 1375 goto out; … … 1368 1377 Assert(uLBA == uLastGrainWritten * pExtent->cSectorsPerGrain); 1369 1378 pExtent->uGrainSector = uLastGrainSector; 1370 pExtent->cbLastGrainWritten = RT_ALIGN(cbMarker, 512);1379 pExtent->cbLastGrainWritten = cbMarker; 1371 1380 } 1372 1381 pExtent->uLastGrainWritten = uLastGrainWritten; … … 1425 1434 cbOverhead = RT_ALIGN_64(cbOverhead, 1426 1435 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 1427 if (pExtent->fFooter) 1428 rc = vmdkFileSetSize(pImage, pExtent->pFile, cbOverhead); 1429 else 1436 if (!pExtent->fFooter) 1430 1437 rc = vmdkFileSetSize(pImage, pExtent->pFile, cbOverhead + 512); 1431 1438 } … … 1499 1506 } 1500 1507 pExtent->cOverheadSectors = VMDK_BYTE2SECTOR(cbOverhead); 1508 1509 /* streamOptimized extents need a compressed grain buffer, which must 1510 * be big enough to hold uncompressible data (which needs ~8 bytes 1511 * more than the uncompressed data), the marker and padding. */ 1512 pExtent->cbCompGrain = RT_ALIGN_Z( VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain) 1513 + 8 + sizeof(VMDKMARKER), 512); 1514 pExtent->pvCompGrain = RTMemAlloc(pExtent->cbCompGrain); 1515 if (!pExtent->pvCompGrain) 1516 { 1517 rc = VERR_NO_MEMORY; 1518 goto out; 1519 } 1501 1520 1502 1521 /* streamOptimized extents need a grain decompress buffer. */ … … 4500 4519 } 4501 4520 4521 /* Skip over the overhead area. */ 4522 rc = vmdkFileSetSize(pImage, pExtent->pFile, 4523 VMDK_SECTOR2BYTE(pExtent->cOverheadSectors)); 4524 4502 4525 if (pfnProgress) 4503 4526 pfnProgress(pvUser, uPercentStart + uPercentSpan * 70 / 100); … … 5236 5259 Assert(cbWrite == VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 5237 5260 uint32_t cbGrain = 0; 5238 rc = vmdkFileDeflateSync(pImage, pExtent ->pFile, cbExtentSize,5239 pvBuf, cbWrite, VMDK_MARKER_IGNORE,uSector, &cbGrain);5261 rc = vmdkFileDeflateSync(pImage, pExtent, cbExtentSize, 5262 pvBuf, cbWrite, uSector, &cbGrain); 5240 5263 if (RT_FAILURE(rc)) 5241 5264 { … … 5245 5268 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname); 5246 5269 } 5247 cbGrain = RT_ALIGN(cbGrain, 512);5248 5270 pExtent->uLastGrainSector = VMDK_BYTE2SECTOR(cbExtentSize); 5249 5271 pExtent->uLastGrainWritten = uSector / pExtent->cSectorsPerGrain; … … 5954 5976 pData = pExtent->pvGrain; 5955 5977 } 5956 rc = vmdkFileDeflateSync(pImage, pExtent ->pFile, uFileOffset,5957 pData,VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain),5958 VMDK_MARKER_IGNORE,uSector, &cbGrain);5978 rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset, pData, 5979 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 5980 uSector, &cbGrain); 5959 5981 if (RT_FAILURE(rc)) 5960 5982 { … … 5964 5986 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname); 5965 5987 } 5966 cbGrain = RT_ALIGN(cbGrain, 512);5967 5988 pExtent->uLastGrainSector = VMDK_BYTE2SECTOR(uFileOffset); 5968 5989 pExtent->uLastGrainWritten = uGrain; … … 6703 6724 if (pExtent->uGrainSector != uSectorExtentAbs) 6704 6725 { 6705 rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs), 6706 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL); 6726 rc = vmdkFileInflateSync(pImage, pExtent, 6727 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6728 pExtent->pvGrain, 6729 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 6730 &uLBA, NULL); 6707 6731 if (RT_FAILURE(rc)) 6708 6732 { … … 6844 6868 || pExtent->uGrainSector != pExtent->uLastGrainSector) 6845 6869 { 6846 rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs), 6847 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL); 6870 rc = vmdkFileInflateSync(pImage, pExtent, 6871 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6872 pExtent->pvGrain, 6873 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 6874 &uLBA, NULL); 6848 6875 if (RT_FAILURE(rc)) 6849 6876 { … … 6859 6886 memcpy((uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), pvBuf, cbToWrite); 6860 6887 uint32_t cbGrain = 0; 6861 rc = vmdkFileDeflateSync(pImage, pExtent ->pFile,6888 rc = vmdkFileDeflateSync(pImage, pExtent, 6862 6889 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6863 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 6864 VMDK_MARKER_IGNORE, uLBA, &cbGrain); 6890 pExtent->pvGrain, 6891 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 6892 uLBA, &cbGrain); 6865 6893 if (RT_FAILURE(rc)) 6866 6894 { … … 6870 6898 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname); 6871 6899 } 6872 cbGrain = RT_ALIGN(cbGrain, 512);6873 6900 pExtent->uLastGrainSector = uSectorExtentAbs; 6874 6901 pExtent->uLastGrainWritten = uSectorExtentRel / pExtent->cSectorsPerGrain;
Note:
See TracChangeset
for help on using the changeset viewer.