Changeset 18067 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Mar 18, 2009 2:17:49 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r17970 r18067 304 304 /** Flag whether the metadata in the extent header needs to be updated. */ 305 305 bool fMetaDirty; 306 /** Flag whether there is a footer in this extent. */ 307 bool fFooter; 306 308 /** Compression type for this extent. */ 307 309 uint16_t uCompression; … … 2460 2462 && RT_LE2H_U64(Header.gdOffset) == VMDK_GD_AT_END) 2461 2463 { 2462 /* Extent with markers. Use this as criteria to read the footer, as 2463 * the spec is as usual totally fuzzy what the criteria really is. */ 2464 /* Read the footer, which isn't compressed and comes before the 2465 * end-of-stream marker. This is bending the VMDK 1.1 spec, but that's 2466 * VMware reality. Theory and practice have very little in common. */ 2464 2467 uint64_t cbSize; 2465 2468 rc = vmdkFileGetSize(pExtent->pFile, &cbSize); … … 2471 2474 } 2472 2475 cbSize = RT_ALIGN_64(cbSize, 512); 2473 rc = vmdkFile InflateAt(pExtent->pFile, cbSize - 2 * 512, &Header, sizeof(Header), VMDK_MARKER_FOOTER, NULL, NULL);2476 rc = vmdkFileReadAt(pExtent->pFile, cbSize - 2*512, &Header, sizeof(Header), NULL); 2474 2477 AssertRC(rc); 2475 2478 if (RT_FAILURE(rc)) … … 2481 2484 if (RT_FAILURE(rc)) 2482 2485 goto out; 2486 pExtent->fFooter = true; 2483 2487 } 2484 2488 pExtent->uVersion = RT_LE2H_U32(Header.version); … … 2600 2604 * Internal: write/update the metadata for a sparse extent. 2601 2605 */ 2602 static int vmdkWriteMetaSparseExtent(PVMDKEXTENT pExtent )2606 static int vmdkWriteMetaSparseExtent(PVMDKEXTENT pExtent, uint64_t uOffset) 2603 2607 { 2604 2608 SparseExtentHeader Header; … … 2606 2610 memset(&Header, '\0', sizeof(Header)); 2607 2611 Header.magicNumber = RT_H2LE_U32(VMDK_SPARSE_MAGICNUMBER); 2608 Header.version = RT_H2LE_U32( 1);2612 Header.version = RT_H2LE_U32(pExtent->uVersion); 2609 2613 Header.flags = RT_H2LE_U32(RT_BIT(0)); 2610 2614 if (pExtent->pRGD) … … 2617 2621 Header.descriptorSize = RT_H2LE_U64(pExtent->cDescriptorSectors); 2618 2622 Header.numGTEsPerGT = RT_H2LE_U32(pExtent->cGTEntries); 2619 if (pExtent->pRGD) 2620 { 2621 Assert(pExtent->uSectorRGD); 2622 Header.rgdOffset = RT_H2LE_U64(pExtent->uSectorRGD); 2623 Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD); 2623 if (pExtent->fFooter && uOffset == 0) 2624 { 2625 if (pExtent->pRGD) 2626 { 2627 Assert(pExtent->uSectorRGD); 2628 Header.rgdOffset = RT_H2LE_U64(VMDK_GD_AT_END); 2629 Header.gdOffset = RT_H2LE_U64(VMDK_GD_AT_END); 2630 } 2631 else 2632 { 2633 Header.gdOffset = RT_H2LE_U64(VMDK_GD_AT_END); 2634 } 2624 2635 } 2625 2636 else 2626 2637 { 2627 Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD); 2638 if (pExtent->pRGD) 2639 { 2640 Assert(pExtent->uSectorRGD); 2641 Header.rgdOffset = RT_H2LE_U64(pExtent->uSectorRGD); 2642 Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD); 2643 } 2644 else 2645 { 2646 Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD); 2647 } 2628 2648 } 2629 2649 Header.overHead = RT_H2LE_U64(pExtent->cOverheadSectors); … … 2635 2655 Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression); 2636 2656 2637 int rc = vmdkFileWriteAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL);2657 int rc = vmdkFileWriteAt(pExtent->pFile, uOffset, &Header, sizeof(Header), NULL); 2638 2658 AssertRC(rc); 2639 2659 if (RT_FAILURE(rc)) … … 3562 3582 cSectorsPerGD = (pExtent->cGDEntries + (512 / sizeof(uint32_t) - 1)) / (512 / sizeof(uint32_t)); 3563 3583 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 3584 { 3585 /* The spec says version is 1 for all VMDKs, but the vast 3586 * majority of streamOptimized VMDKs actually contain 3587 * version 3 - so go with the majority. Both are acepted. */ 3588 pExtent->uVersion = 3; 3564 3589 pExtent->uCompression = VMDK_COMPRESSION_DEFLATE; 3590 } 3565 3591 } 3566 3592 else … … 3821 3847 } 3822 3848 } 3823 (void)vmdkFlushImage(pImage); 3849 /* Don't attempt to flush the image if there is no file - usually happens 3850 * when creating fails for whatever reason. */ 3851 if (pImage->pFile != NULL) 3852 (void)vmdkFlushImage(pImage); 3824 3853 3825 3854 if (pImage->pExtents != NULL) … … 3870 3899 { 3871 3900 case VMDKETYPE_HOSTED_SPARSE: 3872 rc = vmdkWriteMetaSparseExtent(pExtent );3901 rc = vmdkWriteMetaSparseExtent(pExtent, 0); 3873 3902 if (RT_FAILURE(rc)) 3874 3903 goto out; 3904 if (pExtent->fFooter) 3905 { 3906 uint64_t cbSize; 3907 rc = vmdkFileGetSize(pExtent->pFile, &cbSize); 3908 if (RT_FAILURE(rc)) 3909 goto out; 3910 cbSize = RT_ALIGN_64(cbSize, 512); 3911 rc = vmdkWriteMetaSparseExtent(pExtent, cbSize - 2*512); 3912 if (RT_FAILURE(rc)) 3913 goto out; 3914 } 3875 3915 break; 3876 3916 #ifdef VBOX_WITH_VMDK_ESX … … 4042 4082 uGTSector = VMDK_BYTE2SECTOR(cbExtentSize); 4043 4083 /* For writable streamOptimized extents the final sector is the 4044 * end-of-stream marker. Will be re-added after the grain table. */ 4084 * end-of-stream marker. Will be re-added after the grain table. 4085 * If the file has a footer it also will be re-added before EOS. */ 4045 4086 if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 4046 4087 { 4088 uint64_t uEOSOff = 0; 4047 4089 uGTSector--; 4090 if (pExtent->fFooter) 4091 { 4092 uGTSector--; 4093 uEOSOff = 512; 4094 rc = vmdkWriteMetaSparseExtent(pExtent, VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t)); 4095 if (RT_FAILURE(rc)) 4096 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after grain table in '%s'"), pExtent->pszFullname); 4097 } 4048 4098 pExtent->uLastGrainSector = 0; 4049 4099 uint8_t aEOS[512]; 4050 4100 memset(aEOS, '\0', sizeof(aEOS)); 4051 4101 rc = vmdkFileWriteAt(pExtent->pFile, 4052 VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t) ,4102 VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff, 4053 4103 aEOS, sizeof(aEOS), NULL); 4054 4104 if (RT_FAILURE(rc)) … … 4084 4134 uRGTSector = VMDK_BYTE2SECTOR(cbExtentSize); 4085 4135 /* For writable streamOptimized extents the final sector is the 4086 * end-of-stream marker. Will be re-added after the grain table. */ 4136 * end-of-stream marker. Will be re-added after the grain table. 4137 * If the file has a footer it also will be re-added before EOS. */ 4087 4138 if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 4088 4139 { 4140 uint64_t uEOSOff = 0; 4089 4141 uRGTSector--; 4142 if (pExtent->fFooter) 4143 { 4144 uRGTSector--; 4145 uEOSOff = 512; 4146 rc = vmdkWriteMetaSparseExtent(pExtent, VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t)); 4147 if (RT_FAILURE(rc)) 4148 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after redundant grain table in '%s'"), pExtent->pszFullname); 4149 } 4090 4150 pExtent->uLastGrainSector = 0; 4091 4151 uint8_t aEOS[512]; 4092 4152 memset(aEOS, '\0', sizeof(aEOS)); 4093 4153 rc = vmdkFileWriteAt(pExtent->pFile, 4094 VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t) ,4154 VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff, 4095 4155 aEOS, sizeof(aEOS), NULL); 4096 4156 if (RT_FAILURE(rc)) … … 4157 4217 * Additionally the end-of-stream marker needs to be written. */ 4158 4218 if (!pExtent->uLastGrainSector) 4219 { 4159 4220 cbExtentSize -= 512; 4221 if (pExtent->fFooter) 4222 cbExtentSize -= 512; 4223 } 4160 4224 else 4161 4225 cbExtentSize = VMDK_SECTOR2BYTE(pExtent->uLastGrainSector) + pExtent->cbLastGrainWritten; … … 4178 4242 pExtent->uGrainSector = uSector; 4179 4243 4244 uint64_t uEOSOff = 0; 4245 if (pExtent->fFooter) 4246 { 4247 uEOSOff = 512; 4248 rc = vmdkWriteMetaSparseExtent(pExtent, cbExtentSize + RT_ALIGN(cbGrain, 512)); 4249 if (RT_FAILURE(rc)) 4250 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after allocated data block in '%s'"), pExtent->pszFullname); 4251 } 4180 4252 uint8_t aEOS[512]; 4181 4253 memset(aEOS, '\0', sizeof(aEOS)); 4182 rc = vmdkFileWriteAt(pExtent->pFile, cbExtentSize + RT_ALIGN(cbGrain, 512) ,4254 rc = vmdkFileWriteAt(pExtent->pFile, cbExtentSize + RT_ALIGN(cbGrain, 512) + uEOSOff, 4183 4255 aEOS, sizeof(aEOS), NULL); 4184 4256 if (RT_FAILURE(rc)) … … 4957 5029 pExtent->cbLastGrainWritten = cbGrain; 4958 5030 5031 uint64_t uEOSOff = 0; 5032 if (pExtent->fFooter) 5033 { 5034 uEOSOff = 512; 5035 rc = vmdkWriteMetaSparseExtent(pExtent, VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512)); 5036 if (RT_FAILURE(rc)) 5037 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after data block in '%s'"), pExtent->pszFullname); 5038 } 4959 5039 uint8_t aEOS[512]; 4960 5040 memset(aEOS, '\0', sizeof(aEOS)); 4961 5041 rc = vmdkFileWriteAt(pExtent->pFile, 4962 VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512) ,5042 VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512) + uEOSOff, 4963 5043 aEOS, sizeof(aEOS), NULL); 4964 5044 if (RT_FAILURE(rc))
Note:
See TracChangeset
for help on using the changeset viewer.