Changeset 33182 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Oct 18, 2010 8:30:05 AM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 66718
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DMGHDDCore.cpp
r32768 r33182 2096 2096 int rc; 2097 2097 2098 /* Image must be opened and the new flags must be valid. Just readonly and 2099 * info flags are supported. */ 2100 if (!pThis || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO || VD_OPEN_FLAGS_SHAREABLE))) 2098 /* Image must be opened and the new flags must be valid. */ 2099 if (!pThis || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO || VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL))) 2101 2100 { 2102 2101 rc = VERR_INVALID_PARAMETER; -
trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp
r33124 r33182 4893 4893 int rc; 4894 4894 4895 /* Image must be opened and the new flags must be valid. Just readonly and 4896 * info flags are supported. */ 4897 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 4895 /* Image must be opened and the new flags must be valid. */ 4896 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL))) 4898 4897 { 4899 4898 rc = VERR_INVALID_PARAMETER; -
trunk/src/VBox/Devices/Storage/ParallelsHDDCore.cpp
r32553 r33182 957 957 int rc; 958 958 959 /* Image must be opened and the new flags must be valid. Just readonly and 960 * info flags are supported. */ 959 /* Image must be opened and the new flags must be valid. */ 961 960 /** @todo r=klaus add VD_OPEN_FLAGS_ASYNC_IO when async io has been tested */ 962 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE )))961 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL))) 963 962 { 964 963 rc = VERR_INVALID_PARAMETER; -
trunk/src/VBox/Devices/Storage/RawHDDCore.cpp
r32598 r33182 926 926 int rc; 927 927 928 /* Image must be opened and the new flags must be valid. Just readonly and 929 * info flags are supported. */ 930 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 928 /* Image must be opened and the new flags must be valid. */ 929 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL))) 931 930 { 932 931 rc = VERR_INVALID_PARAMETER; -
trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp
r33081 r33182 1636 1636 const char *pszFilename; 1637 1637 1638 /* Image must be opened and the new flags must be valid. Just readonly and 1639 * info flags are supported. */ 1640 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 1638 /* Image must be opened and the new flags must be valid. */ 1639 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL))) 1641 1640 { 1642 1641 rc = VERR_INVALID_PARAMETER; -
trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp
r33131 r33182 2080 2080 int rc; 2081 2081 2082 /* Image must be opened and the new flags must be valid. Just readonly and 2083 * info flags are supported. */ 2084 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 2082 /* Image must be opened and the new flags must be valid. */ 2083 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL))) 2085 2084 { 2086 2085 rc = VERR_INVALID_PARAMETER; -
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r33088 r33182 306 306 /** Append position for writing new grain. Only for sparse extents. */ 307 307 uint64_t uAppendPosition; 308 /** Last grain which has been written to. Only for streamOptimized extents. */ 309 uint32_t uLastGrainWritten; 310 /** Sector number of last grain which has been written to. Only for 311 * streamOptimized extents. */ 312 uint32_t uLastGrainSector; 313 /** Starting sector of the decompressed grain buffer. */ 314 uint32_t uGrainSector; 308 /** Last grain which was accessed. Only for streamOptimized extents. */ 309 uint32_t uLastGrainAccess; 310 /** Starting sector corresponding to the grain buffer. */ 311 uint32_t uGrainSectorAbs; 312 /** Grain number corresponding to the grain buffer. */ 313 uint32_t uGrain; 314 /** Actual size of the compressed data, only valid for reading. */ 315 uint32_t cbGrainStreamRead; 315 316 /** Size of compressed grain buffer for streamOptimized extents. */ 316 317 size_t cbCompGrain; … … 523 524 *******************************************************************************/ 524 525 526 static void vmdkFreeStreamBuffers(PVMDKEXTENT pExtent); 525 527 static void vmdkFreeExtentData(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 526 528 bool fDelete); … … 869 871 DECLINLINE(int) vmdkFileInflateSync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 870 872 uint64_t uOffset, void *pvBuf, 871 size_t cbToRead, uint64_t *puLBA,872 uint 32_t *pcbMarkerData)873 size_t cbToRead, const void *pcvMarker, 874 uint64_t *puLBA, uint32_t *pcbMarkerData) 873 875 { 874 876 if (pExtent->pFile->fAsyncIO) … … 884 886 size_t cbCompSize, cbActuallyRead; 885 887 886 rc = vmdkFileReadSync(pImage, pExtent->pFile, uOffset, pMarker, 887 RT_OFFSETOF(VMDKMARKER, uType), NULL); 888 if (RT_FAILURE(rc)) 889 return rc; 888 if (!pcvMarker) 889 { 890 rc = vmdkFileReadSync(pImage, pExtent->pFile, uOffset, pMarker, 891 RT_OFFSETOF(VMDKMARKER, uType), NULL); 892 if (RT_FAILURE(rc)) 893 return rc; 894 } 895 else 896 memcpy(pMarker, pcvMarker, RT_OFFSETOF(VMDKMARKER, uType)); 897 890 898 cbCompSize = RT_LE2H_U32(pMarker->cbSize); 891 899 if (cbCompSize == 0) … … 1157 1165 1158 1166 /** 1159 * Internal: allocate all buffers associated with grain directories. This1160 * i ncludes the compressed/uncompressed buffers for streamOptimized images.1167 * Internal: allocate the compressed/uncompressed buffers for streamOptimized 1168 * images. 1161 1169 */ 1162 static int vmdkAlloc GrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)1170 static int vmdkAllocStreamBuffers(PVMDKIMAGE pImage, PVMDKEXTENT pExtent) 1163 1171 { 1164 1172 int rc = VINF_SUCCESS; 1165 size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);1166 uint32_t *pGD = NULL, *pRGD = NULL;1167 1168 pGD = (uint32_t *)RTMemAllocZ(cbGD);1169 if (!pGD)1170 {1171 rc = VERR_NO_MEMORY;1172 goto out;1173 }1174 pExtent->pGD = pGD;1175 1176 if (pExtent->uSectorRGD)1177 {1178 pRGD = (uint32_t *)RTMemAllocZ(cbGD);1179 if (!pRGD)1180 {1181 rc = VERR_NO_MEMORY;1182 goto out;1183 }1184 pExtent->pRGD = pRGD;1185 }1186 1173 1187 1174 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) … … 1210 1197 out: 1211 1198 if (RT_FAILURE(rc)) 1199 vmdkFreeStreamBuffers(pExtent); 1200 return rc; 1201 } 1202 1203 /** 1204 * Internal: allocate all buffers associated with grain directories. 1205 */ 1206 static int vmdkAllocGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent) 1207 { 1208 int rc = VINF_SUCCESS; 1209 size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t); 1210 uint32_t *pGD = NULL, *pRGD = NULL; 1211 1212 pGD = (uint32_t *)RTMemAllocZ(cbGD); 1213 if (!pGD) 1214 { 1215 rc = VERR_NO_MEMORY; 1216 goto out; 1217 } 1218 pExtent->pGD = pGD; 1219 1220 if (pExtent->uSectorRGD) 1221 { 1222 pRGD = (uint32_t *)RTMemAllocZ(cbGD); 1223 if (!pRGD) 1224 { 1225 rc = VERR_NO_MEMORY; 1226 goto out; 1227 } 1228 pExtent->pRGD = pRGD; 1229 } 1230 1231 out: 1232 if (RT_FAILURE(rc)) 1212 1233 vmdkFreeGrainDirectory(pExtent); 1213 1234 return rc; … … 1223 1244 if (pExtent->enmType != VMDKETYPE_HOSTED_SPARSE) 1224 1245 goto out; 1246 1247 if ( pExtent->uSectorGD == VMDK_GD_AT_END 1248 || pExtent->uSectorRGD == VMDK_GD_AT_END) 1249 { 1250 rc = VERR_INTERNAL_ERROR; 1251 goto out; 1252 } 1225 1253 1226 1254 rc = vmdkAllocGrainDirectory(pImage, pExtent); … … 1390 1418 pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded); 1391 1419 } 1420 1421 rc = vmdkAllocStreamBuffers(pImage, pExtent); 1422 if (RT_FAILURE(rc)) 1423 goto out; 1392 1424 1393 1425 rc = vmdkAllocGrainDirectory(pImage, pExtent); … … 2676 2708 * as found in monolithic files. 2677 2709 */ 2678 static int vmdkReadBinaryMetaExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent) 2710 static int vmdkReadBinaryMetaExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 2711 bool fMagicAlreadyRead) 2679 2712 { 2680 2713 SparseExtentHeader Header; 2681 2714 uint64_t cSectorsPerGDE; 2682 2683 int rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, sizeof(Header), NULL); 2715 uint64_t cbFile = 0; 2716 int rc; 2717 2718 if (fMagicAlreadyRead) 2719 rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, 2720 sizeof(Header), NULL); 2721 else 2722 { 2723 Header.magicNumber = RT_H2LE_U32(VMDK_SPARSE_MAGICNUMBER); 2724 rc = vmdkFileReadSync(pImage, pExtent->pFile, 2725 RT_OFFSETOF(SparseExtentHeader, version), 2726 &Header.version, 2727 sizeof(Header) 2728 - RT_OFFSETOF(SparseExtentHeader, version), 2729 NULL); 2730 } 2684 2731 AssertRC(rc); 2685 2732 if (RT_FAILURE(rc)) … … 2692 2739 goto out; 2693 2740 2694 rc = vmdkFileGetSize(pImage, pExtent->pFile, &pExtent->uAppendPosition);2695 AssertRC(rc);2696 if (RT_FAILURE(rc))2697 {2698 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname);2699 goto out;2700 }2701 pExtent->uAppendPosition = RT_ALIGN_64(pExtent->uAppendPosition, 512);2702 2703 2741 if ( RT_LE2H_U32(Header.flags & RT_BIT(17)) 2704 2742 && RT_LE2H_U64(Header.gdOffset) == VMDK_GD_AT_END) 2743 pExtent->fFooter = true; 2744 2745 if ( !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2746 || ( pExtent->fFooter 2747 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))) 2748 { 2749 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbFile); 2750 AssertRC(rc); 2751 if (RT_FAILURE(rc)) 2752 { 2753 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname); 2754 goto out; 2755 } 2756 } 2757 2758 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2759 pExtent->uAppendPosition = RT_ALIGN_64(cbFile, 512); 2760 2761 if ( !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2762 || ( pExtent->fFooter 2763 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))) 2705 2764 { 2706 2765 /* Read the footer, which comes before the end-of-stream marker. */ 2707 2766 rc = vmdkFileReadSync(pImage, pExtent->pFile, 2708 pExtent->uAppendPosition- 2*512, &Header,2767 cbFile - 2*512, &Header, 2709 2768 sizeof(Header), NULL); 2710 2769 AssertRC(rc); … … 2717 2776 if (RT_FAILURE(rc)) 2718 2777 goto out; 2719 pExtent->fFooter = true;2720 2778 /* Prohibit any writes to this extent. */ 2721 2779 pExtent->uAppendPosition = 0; 2722 2780 } 2781 2723 2782 pExtent->uVersion = RT_LE2H_U32(Header.version); 2724 2783 pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; /* Just dummy value, changed later. */ … … 2743 2802 pExtent->uSectorRGD = 0; 2744 2803 } 2745 if (pExtent->uSectorGD == VMDK_GD_AT_END || pExtent->uSectorRGD == VMDK_GD_AT_END) 2804 if ( ( pExtent->uSectorGD == VMDK_GD_AT_END 2805 || pExtent->uSectorRGD == VMDK_GD_AT_END) 2806 && ( !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2807 || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))) 2746 2808 { 2747 2809 rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot resolve grain directory offset in '%s'"), pExtent->pszFullname); … … 2786 2848 { 2787 2849 int rc = VINF_SUCCESS; 2850 2851 /* disabled the check as there are too many truncated vmdk images out there */ 2852 #ifdef VBOX_WITH_VMDK_STRICT_SIZE_CHECK 2788 2853 uint64_t cbExtentSize; 2789 2790 2854 /* The image must be a multiple of a sector in size and contain the data 2791 2855 * area (flat images only). If not, it means the image is at least … … 2797 2861 goto out; 2798 2862 } 2799 /* disabled the check as there are too many truncated vmdk images out there */2800 #ifdef VBOX_WITH_VMDK_STRICT_SIZE_CHECK2801 2863 if ( cbExtentSize != RT_ALIGN_64(cbExtentSize, 512) 2802 2864 && (pExtent->enmType != VMDKETYPE_FLAT || pExtent->cNominalSectors + pExtent->uSectorOffset > VMDK_BYTE2SECTOR(cbExtentSize))) … … 2827 2889 } 2828 2890 2891 rc = vmdkAllocStreamBuffers(pImage, pExtent); 2892 if (RT_FAILURE(rc)) 2893 goto out; 2894 2829 2895 /* Prohibit any writes to this streamOptimized extent. */ 2830 2896 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 2831 2897 pExtent->uAppendPosition = 0; 2832 2898 2833 rc = vmdkReadGrainDirectory(pImage, pExtent); 2899 if ( !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 2900 || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2901 || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)) 2902 rc = vmdkReadGrainDirectory(pImage, pExtent); 2903 else 2904 { 2905 pExtent->uGrainSectorAbs = pExtent->cOverheadSectors; 2906 pExtent->cbGrainStreamRead = 0; 2907 } 2834 2908 2835 2909 out: … … 3034 3108 3035 3109 /** 3110 * Internal: free the buffers used for streamOptimized images. 3111 */ 3112 static void vmdkFreeStreamBuffers(PVMDKEXTENT pExtent) 3113 { 3114 if (pExtent->pvCompGrain) 3115 { 3116 RTMemFree(pExtent->pvCompGrain); 3117 pExtent->pvCompGrain = NULL; 3118 } 3119 if (pExtent->pvGrain) 3120 { 3121 RTMemFree(pExtent->pvGrain); 3122 pExtent->pvGrain = NULL; 3123 } 3124 } 3125 3126 /** 3036 3127 * Internal: free the memory used by the extent data structure, optionally 3037 3128 * deleting the referenced files. … … 3064 3155 pExtent->pszFullname = NULL; 3065 3156 } 3066 if (pExtent->pvCompGrain) 3067 { 3068 RTMemFree(pExtent->pvCompGrain); 3069 pExtent->pvCompGrain = NULL; 3070 } 3071 if (pExtent->pvGrain) 3072 { 3073 RTMemFree(pExtent->pvGrain); 3074 pExtent->pvGrain = NULL; 3075 } 3157 vmdkFreeStreamBuffers(pExtent); 3076 3158 } 3077 3159 … … 3208 3290 goto out; 3209 3291 } 3210 rc = vmdkReadBinaryMetaExtent(pImage, pExtent );3292 rc = vmdkReadBinaryMetaExtent(pImage, pExtent, false /* fMagicAlreadyRead */); 3211 3293 if (RT_FAILURE(rc)) 3212 3294 goto out; … … 3399 3481 goto out; 3400 3482 } 3401 rc = vmdkReadBinaryMetaExtent(pImage, pExtent); 3483 rc = vmdkReadBinaryMetaExtent(pImage, pExtent, 3484 true /* fMagicAlreadyRead */); 3402 3485 if (RT_FAILURE(rc)) 3403 3486 goto out; … … 3489 3572 } 3490 3573 3491 rc = vmdkAllocateGrainTableCache(pImage); 3492 if (RT_FAILURE(rc)) 3493 goto out; 3574 if ( !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 3575 || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 3576 || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)) 3577 rc = vmdkAllocateGrainTableCache(pImage); 3494 3578 3495 3579 out: … … 4432 4516 /* No need to write any pending data if the file will be deleted 4433 4517 * or if the new file wasn't successfully created. */ 4434 if (!fDelete && pImage->pExtents && pImage->pExtents[0].cGTEntries) 4518 if ( !fDelete && pImage->pExtents 4519 && pImage->pExtents[0].cGTEntries 4520 && pImage->pExtents[0].uAppendPosition) 4435 4521 { 4436 4522 PVMDKEXTENT pExtent = &pImage->pExtents[0]; 4437 uint32_t uLastGDEntry = pExtent->uLastGrain Written/ pExtent->cGTEntries;4523 uint32_t uLastGDEntry = pExtent->uLastGrainAccess / pExtent->cGTEntries; 4438 4524 if (uLastGDEntry != pExtent->cGDEntries - 1) 4439 4525 { … … 4745 4831 int rc; 4746 4832 4747 /* For newly created streamOptimized images this must be a no-op. */ 4748 if ( pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED 4749 && pExtent->uAppendPosition) 4833 /* For newly created and readonly/sequentially opened streamOptimized 4834 * images this must be a no-op, as the grain directory is not there. */ 4835 if ( ( pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED 4836 && pExtent->uAppendPosition) 4837 || ( pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED 4838 && pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY 4839 && pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)) 4750 4840 { 4751 4841 *puExtentSector = 0; … … 4987 5077 /* Invalidate cache, just in case some code incorrectly allows mixing 4988 5078 * of reads and writes. Normally shouldn't be needed. */ 4989 pExtent->uGrainSector = 0; 4990 pExtent->uLastGrainSector = 0; 5079 pExtent->uGrainSectorAbs = 0; 4991 5080 4992 5081 /* Write compressed data block and the markers. */ … … 4999 5088 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname); 5000 5089 } 5001 pExtent->uLastGrain Written= uSector / pExtent->cSectorsPerGrain;5090 pExtent->uLastGrainAccess = uSector / pExtent->cSectorsPerGrain; 5002 5091 pExtent->uAppendPosition += cbGrain; 5003 5092 } … … 5100 5189 uCacheEntry = uGrain % VMDK_GT_CACHELINE_SIZE; 5101 5190 uGDEntry = uGrain / pExtent->cGTEntries; 5102 uLastGDEntry = pExtent->uLastGrain Written/ pExtent->cGTEntries;5103 if (uGrain < pExtent->uLastGrain Written)5191 uLastGDEntry = pExtent->uLastGrainAccess / pExtent->cGTEntries; 5192 if (uGrain < pExtent->uLastGrainAccess) 5104 5193 return VERR_VD_VMDK_INVALID_WRITE; 5105 5194 … … 5154 5243 if (RT_FAILURE(rc)) 5155 5244 { 5156 pExtent->uGrainSector = 0; 5157 pExtent->uLastGrainSector = 0; 5245 pExtent->uGrainSectorAbs = 0; 5158 5246 AssertRC(rc); 5159 5247 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname); 5160 5248 } 5161 pExtent->uLastGrainSector = VMDK_BYTE2SECTOR(uFileOffset); 5162 pExtent->uLastGrainWritten = uGrain; 5249 pExtent->uLastGrainAccess = uGrain; 5163 5250 pExtent->uAppendPosition += cbGrain; 5164 5251 … … 5470 5557 5471 5558 return rc; 5559 } 5560 5561 /** 5562 * Internal. Reads the contents by sequentially going over the compressed 5563 * grains (hoping that they are in sequence). 5564 */ 5565 static int vmdkStreamReadSequential(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 5566 uint64_t uSector, void *pvBuf, 5567 uint64_t cbRead) 5568 { 5569 int rc; 5570 5571 /* Do not allow to go back. */ 5572 uint32_t uGrain = uSector / pExtent->cSectorsPerGrain; 5573 if (uGrain < pExtent->uLastGrainAccess) 5574 return VERR_VD_VMDK_INVALID_STATE; 5575 pExtent->uLastGrainAccess = uGrain; 5576 5577 /* After a previous error do not attempt to recover, as it would need 5578 * seeking (in the general case backwards which is forbidden). */ 5579 if (!pExtent->uGrainSectorAbs) 5580 return VERR_VD_VMDK_INVALID_STATE; 5581 5582 /* Check if we need to read something from the image or if what we have 5583 * in the buffer is good to fulfill the request. */ 5584 if (!pExtent->cbGrainStreamRead || uGrain > pExtent->uGrain) 5585 { 5586 uint32_t uGrainSectorAbs = pExtent->uGrainSectorAbs 5587 + VMDK_BYTE2SECTOR(pExtent->cbGrainStreamRead); 5588 5589 /* Get the marker from the next data block - and skip everything which 5590 * is not a compressed grain. If it's a compressed grain which is for 5591 * the requested sector (or after), read it. */ 5592 VMDKMARKER Marker; 5593 do 5594 { 5595 RT_ZERO(Marker); 5596 rc = vmdkFileReadSync(pImage, pExtent->pFile, 5597 VMDK_SECTOR2BYTE(uGrainSectorAbs), 5598 &Marker, RT_OFFSETOF(VMDKMARKER, uType), 5599 NULL); 5600 if (RT_FAILURE(rc)) 5601 return rc; 5602 Marker.uSector = RT_LE2H_U64(Marker.uSector); 5603 Marker.cbSize = RT_LE2H_U32(Marker.cbSize); 5604 5605 if (Marker.cbSize == 0) 5606 { 5607 /* A marker for something else than a compressed grain. */ 5608 rc = vmdkFileReadSync(pImage, pExtent->pFile, 5609 VMDK_SECTOR2BYTE(uGrainSectorAbs) 5610 + RT_OFFSETOF(VMDKMARKER, uType), 5611 &Marker.uType, sizeof(Marker.uType), 5612 NULL); 5613 Marker.uType = RT_LE2H_U32(Marker.uType); 5614 switch (Marker.uType) 5615 { 5616 case VMDK_MARKER_EOS: 5617 uGrainSectorAbs++; 5618 break; 5619 case VMDK_MARKER_GT: 5620 uGrainSectorAbs += 1 + VMDK_BYTE2SECTOR(pExtent->cGTEntries * sizeof(uint32_t)); 5621 break; 5622 case VMDK_MARKER_GD: 5623 uGrainSectorAbs += 1 + VMDK_BYTE2SECTOR(RT_ALIGN(pExtent->cGDEntries * sizeof(uint32_t), 512)); 5624 break; 5625 case VMDK_MARKER_FOOTER: 5626 uGrainSectorAbs += 2; 5627 break; 5628 default: 5629 AssertMsgFailed(("VMDK: corrupted marker, type=%#x\n", Marker.uType)); 5630 pExtent->uGrainSectorAbs = 0; 5631 return VERR_VD_VMDK_INVALID_STATE; 5632 } 5633 pExtent->cbGrainStreamRead = 0; 5634 } 5635 else 5636 { 5637 /* A compressed grain marker. If it is at/after what we're 5638 * interested in read and decompress data. */ 5639 if (uSector > Marker.uSector + pExtent->cSectorsPerGrain) 5640 { 5641 uGrainSectorAbs += VMDK_BYTE2SECTOR(RT_ALIGN(Marker.cbSize + RT_OFFSETOF(VMDKMARKER, uType), 512)); 5642 continue; 5643 } 5644 uint64_t uLBA; 5645 uint32_t cbGrainStreamRead = 0; 5646 rc = vmdkFileInflateSync(pImage, pExtent, 5647 VMDK_SECTOR2BYTE(uGrainSectorAbs), 5648 pExtent->pvGrain, 5649 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 5650 &Marker, &uLBA, &cbGrainStreamRead); 5651 if (RT_FAILURE(rc)) 5652 { 5653 pExtent->uGrainSectorAbs = 0; 5654 return rc; 5655 } 5656 if ( pExtent->uGrain 5657 && uLBA / pExtent->cSectorsPerGrain <= pExtent->uGrain) 5658 { 5659 pExtent->uGrainSectorAbs = 0; 5660 return VERR_VD_VMDK_INVALID_STATE; 5661 } 5662 pExtent->uGrain = uLBA / pExtent->cSectorsPerGrain; 5663 pExtent->cbGrainStreamRead = cbGrainStreamRead; 5664 break; 5665 } 5666 } while (Marker.uType != VMDK_MARKER_EOS); 5667 5668 pExtent->uGrainSectorAbs = uGrainSectorAbs; 5669 5670 if (!pExtent->cbGrainStreamRead && Marker.uType == VMDK_MARKER_EOS) 5671 { 5672 pExtent->uGrain = UINT32_MAX; 5673 /* Must set a non-zero value for pExtent->cbGrainStreamRead or 5674 * the next read would try to get more data, and we're at EOF. */ 5675 pExtent->cbGrainStreamRead = 1; 5676 } 5677 } 5678 5679 if (pExtent->uGrain > uSector / pExtent->cSectorsPerGrain) 5680 { 5681 /* The next data block we have is not for this area, so just return 5682 * that there is no data. */ 5683 return VERR_VD_BLOCK_FREE; 5684 } 5685 5686 uint32_t uSectorInGrain = uSector % pExtent->cSectorsPerGrain; 5687 memcpy(pvBuf, 5688 (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), 5689 cbRead); 5690 return VINF_SUCCESS; 5472 5691 } 5473 5692 … … 6021 6240 Assert(!(cbToRead % 512)); 6022 6241 if (uSectorExtentAbs == 0) 6023 rc = VERR_VD_BLOCK_FREE; 6242 { 6243 if ( !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 6244 || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 6245 || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)) 6246 rc = VERR_VD_BLOCK_FREE; 6247 else 6248 rc = vmdkStreamReadSequential(pImage, pExtent, 6249 uSectorExtentRel, 6250 pvBuf, cbToRead); 6251 } 6024 6252 else 6025 6253 { … … 6029 6257 uSectorExtentAbs -= uSectorInGrain; 6030 6258 uint64_t uLBA; 6031 if (pExtent->uGrainSector != uSectorExtentAbs)6259 if (pExtent->uGrainSectorAbs != uSectorExtentAbs) 6032 6260 { 6033 6261 rc = vmdkFileInflateSync(pImage, pExtent, … … 6035 6263 pExtent->pvGrain, 6036 6264 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 6037 &uLBA, NULL);6265 NULL, &uLBA, NULL); 6038 6266 if (RT_FAILURE(rc)) 6039 6267 { 6040 pExtent->uGrainSector = 0;6268 pExtent->uGrainSectorAbs = 0; 6041 6269 AssertRC(rc); 6042 6270 goto out; 6043 6271 } 6044 pExtent->uGrainSector = uSectorExtentAbs; 6272 pExtent->uGrainSectorAbs = uSectorExtentAbs; 6273 pExtent->uGrain = uSectorExtentRel / pExtent->cSectorsPerGrain; 6045 6274 Assert(uLBA == uSectorExtentRel); 6046 6275 } … … 6137 6366 cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain)); 6138 6367 if ( pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED 6139 && uSectorExtentRel < (uint64_t)pExtent->uLastGrain Written* pExtent->cSectorsPerGrain)6368 && uSectorExtentRel < (uint64_t)pExtent->uLastGrainAccess * pExtent->cSectorsPerGrain) 6140 6369 { 6141 6370 rc = VERR_VD_VMDK_INVALID_WRITE; … … 6186 6415 * which is somewhere between expensive and impossible. */ 6187 6416 rc = VERR_VD_VMDK_INVALID_STATE; 6188 pExtent->uGrainSector = 0; 6189 pExtent->uLastGrainSector = 0; 6417 pExtent->uGrainSectorAbs = 0; 6190 6418 AssertRC(rc); 6191 6419 } … … 6464 6692 int rc; 6465 6693 6466 /* Image must be opened and the new flags must be valid. Just readonly and 6467 * info flags are supported. */ 6468 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 6694 /* Image must be opened and the new flags must be valid. */ 6695 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL))) 6469 6696 { 6470 6697 rc = VERR_INVALID_PARAMETER; … … 6965 7192 cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain)); 6966 7193 if ( pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED 6967 && uSectorExtentRel < (uint64_t)pExtent->uLastGrain Written* pExtent->cSectorsPerGrain)7194 && uSectorExtentRel < (uint64_t)pExtent->uLastGrainAccess * pExtent->cSectorsPerGrain) 6968 7195 { 6969 7196 rc = VERR_VD_VMDK_INVALID_WRITE;
Note:
See TracChangeset
for help on using the changeset viewer.