Changeset 44252 in vbox for trunk/src/VBox/Storage
- Timestamp:
- Jan 8, 2013 1:23:54 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 83113
- Location:
- trunk/src/VBox/Storage
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/DMG.cpp
r44233 r44252 1660 1660 1661 1661 /** @copydoc VBOXHDDBACKEND::pfnRead */ 1662 static int dmgRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 1663 size_t cbToRead, size_t *pcbActuallyRead) 1664 { 1665 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 1662 static int dmgRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 1663 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1664 { 1665 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1666 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 1666 1667 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1667 1668 PDMGEXTENT pExtent = NULL; … … 1692 1693 case DMGEXTENTTYPE_RAW: 1693 1694 { 1694 rc = vdIfIoIntFileRead Sync(pThis->pIfIo, pThis->pStorage,1695 rc = vdIfIoIntFileReadUser(pThis->pIfIo, pThis->pStorage, 1695 1696 pExtent->offFileStart + DMG_BLOCK2BYTE(uExtentRel), 1696 p vBuf, cbToRead);1697 pIoCtx, cbToRead); 1697 1698 break; 1698 1699 } 1699 1700 case DMGEXTENTTYPE_ZERO: 1700 1701 { 1701 memset(pvBuf, 0, cbToRead);1702 vdIfIoIntIoCtxSet(pThis->pIfIo, pIoCtx, 0, cbToRead); 1702 1703 break; 1703 1704 } … … 1729 1730 1730 1731 if (RT_SUCCESS(rc)) 1731 memcpy(pvBuf, (uint8_t *)pThis->pvDecompExtent + DMG_BLOCK2BYTE(uExtentRel), cbToRead); 1732 vdIfIoIntIoCtxCopyTo(pThis->pIfIo, pIoCtx, 1733 (uint8_t *)pThis->pvDecompExtent + DMG_BLOCK2BYTE(uExtentRel), 1734 cbToRead); 1732 1735 break; 1733 1736 } … … 1748 1751 1749 1752 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1750 static int dmgWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,1751 size_t cbToWrite, size_t *pcbWriteProcess,1752 size_t *pcbP reRead, size_t *pcbPostRead, unsigned fWrite)1753 { 1754 LogFlowFunc(("pBackendData=%#p uOffset=%llu p vBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",1755 pBackendData, uOffset, p vBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));1753 static int dmgWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 1754 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 1755 size_t *pcbPostRead, unsigned fWrite) 1756 { 1757 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 1758 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 1756 1759 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1757 1760 int rc = VERR_NOT_IMPLEMENTED; … … 1775 1778 1776 1779 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1777 static int dmgFlush(void *pBackendData )1780 static int dmgFlush(void *pBackendData, PVDIOCTX pIoCtx) 1778 1781 { 1779 1782 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); … … 2269 2272 /* pfnFlush */ 2270 2273 dmgFlush, 2274 /* pfnDiscard */ 2275 NULL, 2271 2276 /* pfnGetVersion */ 2272 2277 dmgGetVersion, … … 2321 2326 /* pfnSetParentFilename */ 2322 2327 NULL, 2323 /* pfnAsyncRead */2324 NULL,2325 /* pfnAsyncWrite */2326 NULL,2327 /* pfnAsyncFlush */2328 NULL,2329 2328 /* pfnComposeLocation */ 2330 2329 genericFileComposeLocation, … … 2335 2334 /* pfnResize */ 2336 2335 NULL, 2337 /* pfnDiscard */2338 NULL,2339 /* pfnAsyncDiscard */2340 NULL,2341 2336 /* pfnRepair */ 2342 2337 NULL -
trunk/src/VBox/Storage/ISCSI.cpp
r44242 r44252 4604 4604 } 4605 4605 4606 /** @copydoc VBOXHDDBACKEND::pfnRead */ 4607 static int iscsiRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 4608 size_t cbToRead, size_t *pcbActuallyRead) 4606 static int iscsiReadSync(void *pBackendData, uint64_t uOffset, void *pvBuf, 4607 size_t cbToRead, size_t *pcbActuallyRead) 4609 4608 { 4610 4609 /** @todo reinstate logging of the target everywhere - dropped temporarily */ … … 4706 4705 } 4707 4706 4708 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 4709 static int iscsiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 4710 size_t cbToWrite, size_t *pcbWriteProcess, 4711 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 4707 static int iscsiWriteSync(void *pBackendData, uint64_t uOffset, const void *pvBuf, 4708 size_t cbToWrite, size_t *pcbWriteProcess, 4709 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 4712 4710 { 4713 4711 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); … … 4810 4808 } 4811 4809 4812 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 4813 static int iscsiFlush(void *pBackendData) 4810 static int iscsiFlushSync(void *pBackendData) 4814 4811 { 4815 4812 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); … … 4853 4850 } 4854 4851 4855 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 4856 static unsigned iscsiGetVersion(void *pBackendData) 4857 { 4858 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 4859 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4860 4861 Assert(pImage); 4862 NOREF(pImage); 4863 4864 return 0; 4865 } 4866 4867 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 4868 static uint64_t iscsiGetSize(void *pBackendData) 4869 { 4870 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 4871 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4872 4873 Assert(pImage); 4874 4875 if (pImage) 4876 return pImage->cbSize; 4877 else 4878 return 0; 4879 } 4880 4881 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 4882 static uint64_t iscsiGetFileSize(void *pBackendData) 4883 { 4884 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 4885 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4886 4887 Assert(pImage); 4888 NOREF(pImage); 4889 4890 if (pImage) 4891 return pImage->cbSize; 4892 else 4893 return 0; 4894 } 4895 4896 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 4897 static int iscsiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 4898 { 4899 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 4900 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4901 int rc; 4902 4903 Assert(pImage); 4904 4905 if (pImage) 4906 rc = VERR_VD_GEOMETRY_NOT_SET; 4907 else 4908 rc = VERR_VD_NOT_OPENED; 4909 4910 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 4911 return rc; 4912 } 4913 4914 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 4915 static int iscsiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 4916 { 4917 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 4918 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4919 int rc; 4920 4921 Assert(pImage); 4922 4923 if (pImage) 4924 { 4925 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 4926 { 4927 rc = VERR_VD_IMAGE_READ_ONLY; 4928 goto out; 4929 } 4930 rc = VERR_VD_GEOMETRY_NOT_SET; 4931 } 4932 else 4933 rc = VERR_VD_NOT_OPENED; 4934 4935 out: 4936 LogFlowFunc(("returns %Rrc\n", rc)); 4937 return rc; 4938 } 4939 4940 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 4941 static int iscsiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 4942 { 4943 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 4944 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4945 int rc; 4946 4947 Assert(pImage); 4948 4949 if (pImage) 4950 rc = VERR_VD_GEOMETRY_NOT_SET; 4951 else 4952 rc = VERR_VD_NOT_OPENED; 4953 4954 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 4955 return rc; 4956 } 4957 4958 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 4959 static int iscsiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 4960 { 4961 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 4962 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4963 int rc; 4964 4965 Assert(pImage); 4966 4967 if (pImage) 4968 { 4969 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 4970 { 4971 rc = VERR_VD_IMAGE_READ_ONLY; 4972 goto out; 4973 } 4974 rc = VERR_VD_GEOMETRY_NOT_SET; 4975 } 4976 else 4977 rc = VERR_VD_NOT_OPENED; 4978 4979 out: 4980 LogFlowFunc(("returns %Rrc\n", rc)); 4981 return rc; 4982 } 4983 4984 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 4985 static unsigned iscsiGetImageFlags(void *pBackendData) 4986 { 4987 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 4988 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4989 unsigned uImageFlags; 4990 4991 Assert(pImage); 4992 NOREF(pImage); 4993 4994 uImageFlags = VD_IMAGE_FLAGS_FIXED; 4995 4996 LogFlowFunc(("returns %#x\n", uImageFlags)); 4997 return uImageFlags; 4998 } 4999 5000 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 5001 static unsigned iscsiGetOpenFlags(void *pBackendData) 5002 { 5003 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 5004 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5005 unsigned uOpenFlags; 5006 5007 Assert(pImage); 5008 5009 if (pImage) 5010 uOpenFlags = pImage->uOpenFlags; 5011 else 5012 uOpenFlags = 0; 5013 5014 LogFlowFunc(("returns %#x\n", uOpenFlags)); 5015 return uOpenFlags; 5016 } 5017 5018 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 5019 static int iscsiSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 5020 { 5021 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 5022 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5023 int rc; 5024 5025 /* Image must be opened and the new flags must be valid. */ 5026 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 5027 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE 5028 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 5029 { 5030 rc = VERR_INVALID_PARAMETER; 5031 goto out; 5032 } 5033 5034 /* Implement this operation via reopening the image if we actually need 5035 * to do something. A read/write -> readonly transition doesn't need a 5036 * reopen. In the other direction we don't have the necessary information 5037 * as the "disk is readonly" flag is thrown away. Can be optimized too, 5038 * but it's not worth the effort at the moment. */ 5039 if ( !(uOpenFlags & VD_OPEN_FLAGS_READONLY) 5040 && (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5041 { 5042 iscsiFreeImage(pImage, false); 5043 rc = iscsiOpenImage(pImage, uOpenFlags); 5044 } 5045 else 5046 { 5047 pImage->uOpenFlags = uOpenFlags; 5048 rc = VINF_SUCCESS; 5049 } 5050 out: 5051 LogFlowFunc(("returns %Rrc\n", rc)); 5052 return rc; 5053 } 5054 5055 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 5056 static int iscsiGetComment(void *pBackendData, char *pszComment, 5057 size_t cbComment) 5058 { 5059 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 5060 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5061 int rc; 5062 5063 Assert(pImage); 5064 5065 if (pImage) 5066 rc = VERR_NOT_SUPPORTED; 5067 else 5068 rc = VERR_VD_NOT_OPENED; 5069 5070 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 5071 return rc; 5072 } 5073 5074 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 5075 static int iscsiSetComment(void *pBackendData, const char *pszComment) 5076 { 5077 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 5078 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5079 int rc; 5080 5081 Assert(pImage); 5082 5083 if (pImage) 5084 { 5085 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5086 rc = VERR_NOT_SUPPORTED; 5087 else 5088 rc = VERR_VD_IMAGE_READ_ONLY; 5089 } 5090 else 5091 rc = VERR_VD_NOT_OPENED; 5092 5093 LogFlowFunc(("returns %Rrc\n", rc)); 5094 return rc; 5095 } 5096 5097 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 5098 static int iscsiGetUuid(void *pBackendData, PRTUUID pUuid) 5099 { 5100 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5101 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5102 int rc; 5103 5104 Assert(pImage); 5105 5106 if (pImage) 5107 rc = VERR_NOT_SUPPORTED; 5108 else 5109 rc = VERR_VD_NOT_OPENED; 5110 5111 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5112 return rc; 5113 } 5114 5115 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 5116 static int iscsiSetUuid(void *pBackendData, PCRTUUID pUuid) 5117 { 5118 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5119 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5120 int rc; 5121 5122 LogFlowFunc(("%RTuuid\n", pUuid)); 5123 Assert(pImage); 5124 5125 if (pImage) 5126 { 5127 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5128 rc = VERR_NOT_SUPPORTED; 5129 else 5130 rc = VERR_VD_IMAGE_READ_ONLY; 5131 } 5132 else 5133 rc = VERR_VD_NOT_OPENED; 5134 5135 LogFlowFunc(("returns %Rrc\n", rc)); 5136 return rc; 5137 } 5138 5139 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 5140 static int iscsiGetModificationUuid(void *pBackendData, PRTUUID pUuid) 5141 { 5142 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5143 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5144 int rc; 5145 5146 Assert(pImage); 5147 5148 if (pImage) 5149 rc = VERR_NOT_SUPPORTED; 5150 else 5151 rc = VERR_VD_NOT_OPENED; 5152 5153 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5154 return rc; 5155 } 5156 5157 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 5158 static int iscsiSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 5159 { 5160 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5161 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5162 int rc; 5163 5164 LogFlowFunc(("%RTuuid\n", pUuid)); 5165 Assert(pImage); 5166 5167 if (pImage) 5168 { 5169 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5170 rc = VERR_NOT_SUPPORTED; 5171 else 5172 rc = VERR_VD_IMAGE_READ_ONLY; 5173 } 5174 else 5175 rc = VERR_VD_NOT_OPENED; 5176 5177 LogFlowFunc(("returns %Rrc\n", rc)); 5178 return rc; 5179 } 5180 5181 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 5182 static int iscsiGetParentUuid(void *pBackendData, PRTUUID pUuid) 5183 { 5184 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5185 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5186 int rc; 5187 5188 Assert(pImage); 5189 5190 if (pImage) 5191 rc = VERR_NOT_SUPPORTED; 5192 else 5193 rc = VERR_VD_NOT_OPENED; 5194 5195 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5196 return rc; 5197 } 5198 5199 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 5200 static int iscsiSetParentUuid(void *pBackendData, PCRTUUID pUuid) 5201 { 5202 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5203 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5204 int rc; 5205 5206 LogFlowFunc(("%RTuuid\n", pUuid)); 5207 Assert(pImage); 5208 5209 if (pImage) 5210 { 5211 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5212 rc = VERR_NOT_SUPPORTED; 5213 else 5214 rc = VERR_VD_IMAGE_READ_ONLY; 5215 } 5216 else 5217 rc = VERR_VD_NOT_OPENED; 5218 5219 LogFlowFunc(("returns %Rrc\n", rc)); 5220 return rc; 5221 } 5222 5223 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 5224 static int iscsiGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 5225 { 5226 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5227 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5228 int rc; 5229 5230 Assert(pImage); 5231 5232 if (pImage) 5233 rc = VERR_NOT_SUPPORTED; 5234 else 5235 rc = VERR_VD_NOT_OPENED; 5236 5237 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5238 return rc; 5239 } 5240 5241 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 5242 static int iscsiSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 5243 { 5244 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5245 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5246 int rc; 5247 5248 LogFlowFunc(("%RTuuid\n", pUuid)); 5249 Assert(pImage); 5250 5251 if (pImage) 5252 { 5253 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5254 rc = VERR_NOT_SUPPORTED; 5255 else 5256 rc = VERR_VD_IMAGE_READ_ONLY; 5257 } 5258 else 5259 rc = VERR_VD_NOT_OPENED; 5260 5261 LogFlowFunc(("returns %Rrc\n", rc)); 5262 return rc; 5263 } 5264 5265 /** @copydoc VBOXHDDBACKEND::pfnDump */ 5266 static void iscsiDump(void *pBackendData) 5267 { 5268 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5269 5270 Assert(pImage); 5271 if (pImage) 5272 { 5273 /** @todo put something useful here */ 5274 vdIfErrorMessage(pImage->pIfError, "Header: cVolume=%u\n", pImage->cVolume); 5275 } 5276 } 5277 5278 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */ 5279 static int iscsiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 5280 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 4852 /** @copydoc VBOXHDDBACKEND::pfnRead */ 4853 static int iscsiRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 4854 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 5281 4855 { 5282 4856 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; … … 5306 4880 Assert(cbSegs == cbToRead); 5307 4881 5308 return iscsiRead (pBackendData, uOffset, Segment.pvSeg, cbToRead, pcbActuallyRead);4882 return iscsiReadSync(pBackendData, uOffset, Segment.pvSeg, cbToRead, pcbActuallyRead); 5309 4883 } 5310 4884 … … 5412 4986 5413 4987 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 5414 static int iscsiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 5415 PVDIOCTX pIoCtx, 5416 size_t *pcbWriteProcess, size_t *pcbPreRead, 5417 size_t *pcbPostRead, unsigned fWrite) 4988 static int iscsiWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 4989 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 4990 size_t *pcbPostRead, unsigned fWrite) 5418 4991 { 5419 4992 LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n", … … 5434 5007 cbToWrite = RT_MIN(cbToWrite, pImage->cbSendDataLength); 5435 5008 5436 /** @todo: Remove iscsiWrite and integrate properly. */5009 /** @todo: Remove iscsiWriteSync and integrate properly. */ 5437 5010 if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx)) 5438 5011 { … … 5445 5018 Assert(cbSegs == cbToWrite); 5446 5019 5447 return iscsiWrite (pBackendData, uOffset, Segment.pvSeg, cbToWrite,5448 pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite);5020 return iscsiWriteSync(pBackendData, uOffset, Segment.pvSeg, cbToWrite, 5021 pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite); 5449 5022 } 5450 5023 … … 5551 5124 } 5552 5125 5553 /** @copydoc VBOXHDDBACKEND::pfn AsyncFlush */5554 static int iscsi AsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)5126 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 5127 static int iscsiFlush(void *pBackendData, PVDIOCTX pIoCtx) 5555 5128 { 5556 5129 LogFlowFunc(("pBackendData=%p pIoCtx=%#p\n", pBackendData, pIoCtx)); … … 5558 5131 int rc = VINF_SUCCESS; 5559 5132 5560 /** @todo: Remove iscsiFlush and integrate properly. */5133 /** @todo: Remove iscsiFlushSync and integrate properly. */ 5561 5134 if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx)) 5562 return iscsiFlush (pBackendData);5135 return iscsiFlushSync(pBackendData); 5563 5136 5564 5137 PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(sizeof(SCSIREQASYNC)); … … 5616 5189 LogFlowFunc(("returns rc=%Rrc\n", rc)); 5617 5190 return rc; 5191 } 5192 5193 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 5194 static unsigned iscsiGetVersion(void *pBackendData) 5195 { 5196 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 5197 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5198 5199 Assert(pImage); 5200 NOREF(pImage); 5201 5202 return 0; 5203 } 5204 5205 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 5206 static uint64_t iscsiGetSize(void *pBackendData) 5207 { 5208 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 5209 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5210 5211 Assert(pImage); 5212 5213 if (pImage) 5214 return pImage->cbSize; 5215 else 5216 return 0; 5217 } 5218 5219 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 5220 static uint64_t iscsiGetFileSize(void *pBackendData) 5221 { 5222 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 5223 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5224 5225 Assert(pImage); 5226 NOREF(pImage); 5227 5228 if (pImage) 5229 return pImage->cbSize; 5230 else 5231 return 0; 5232 } 5233 5234 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 5235 static int iscsiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 5236 { 5237 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 5238 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5239 int rc; 5240 5241 Assert(pImage); 5242 5243 if (pImage) 5244 rc = VERR_VD_GEOMETRY_NOT_SET; 5245 else 5246 rc = VERR_VD_NOT_OPENED; 5247 5248 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 5249 return rc; 5250 } 5251 5252 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 5253 static int iscsiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 5254 { 5255 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 5256 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5257 int rc; 5258 5259 Assert(pImage); 5260 5261 if (pImage) 5262 { 5263 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 5264 { 5265 rc = VERR_VD_IMAGE_READ_ONLY; 5266 goto out; 5267 } 5268 rc = VERR_VD_GEOMETRY_NOT_SET; 5269 } 5270 else 5271 rc = VERR_VD_NOT_OPENED; 5272 5273 out: 5274 LogFlowFunc(("returns %Rrc\n", rc)); 5275 return rc; 5276 } 5277 5278 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 5279 static int iscsiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 5280 { 5281 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 5282 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5283 int rc; 5284 5285 Assert(pImage); 5286 5287 if (pImage) 5288 rc = VERR_VD_GEOMETRY_NOT_SET; 5289 else 5290 rc = VERR_VD_NOT_OPENED; 5291 5292 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 5293 return rc; 5294 } 5295 5296 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 5297 static int iscsiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 5298 { 5299 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 5300 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5301 int rc; 5302 5303 Assert(pImage); 5304 5305 if (pImage) 5306 { 5307 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 5308 { 5309 rc = VERR_VD_IMAGE_READ_ONLY; 5310 goto out; 5311 } 5312 rc = VERR_VD_GEOMETRY_NOT_SET; 5313 } 5314 else 5315 rc = VERR_VD_NOT_OPENED; 5316 5317 out: 5318 LogFlowFunc(("returns %Rrc\n", rc)); 5319 return rc; 5320 } 5321 5322 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 5323 static unsigned iscsiGetImageFlags(void *pBackendData) 5324 { 5325 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 5326 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5327 unsigned uImageFlags; 5328 5329 Assert(pImage); 5330 NOREF(pImage); 5331 5332 uImageFlags = VD_IMAGE_FLAGS_FIXED; 5333 5334 LogFlowFunc(("returns %#x\n", uImageFlags)); 5335 return uImageFlags; 5336 } 5337 5338 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 5339 static unsigned iscsiGetOpenFlags(void *pBackendData) 5340 { 5341 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 5342 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5343 unsigned uOpenFlags; 5344 5345 Assert(pImage); 5346 5347 if (pImage) 5348 uOpenFlags = pImage->uOpenFlags; 5349 else 5350 uOpenFlags = 0; 5351 5352 LogFlowFunc(("returns %#x\n", uOpenFlags)); 5353 return uOpenFlags; 5354 } 5355 5356 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 5357 static int iscsiSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 5358 { 5359 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 5360 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5361 int rc; 5362 5363 /* Image must be opened and the new flags must be valid. */ 5364 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 5365 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE 5366 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 5367 { 5368 rc = VERR_INVALID_PARAMETER; 5369 goto out; 5370 } 5371 5372 /* Implement this operation via reopening the image if we actually need 5373 * to do something. A read/write -> readonly transition doesn't need a 5374 * reopen. In the other direction we don't have the necessary information 5375 * as the "disk is readonly" flag is thrown away. Can be optimized too, 5376 * but it's not worth the effort at the moment. */ 5377 if ( !(uOpenFlags & VD_OPEN_FLAGS_READONLY) 5378 && (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5379 { 5380 iscsiFreeImage(pImage, false); 5381 rc = iscsiOpenImage(pImage, uOpenFlags); 5382 } 5383 else 5384 { 5385 pImage->uOpenFlags = uOpenFlags; 5386 rc = VINF_SUCCESS; 5387 } 5388 out: 5389 LogFlowFunc(("returns %Rrc\n", rc)); 5390 return rc; 5391 } 5392 5393 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 5394 static int iscsiGetComment(void *pBackendData, char *pszComment, 5395 size_t cbComment) 5396 { 5397 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 5398 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5399 int rc; 5400 5401 Assert(pImage); 5402 5403 if (pImage) 5404 rc = VERR_NOT_SUPPORTED; 5405 else 5406 rc = VERR_VD_NOT_OPENED; 5407 5408 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 5409 return rc; 5410 } 5411 5412 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 5413 static int iscsiSetComment(void *pBackendData, const char *pszComment) 5414 { 5415 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 5416 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5417 int rc; 5418 5419 Assert(pImage); 5420 5421 if (pImage) 5422 { 5423 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5424 rc = VERR_NOT_SUPPORTED; 5425 else 5426 rc = VERR_VD_IMAGE_READ_ONLY; 5427 } 5428 else 5429 rc = VERR_VD_NOT_OPENED; 5430 5431 LogFlowFunc(("returns %Rrc\n", rc)); 5432 return rc; 5433 } 5434 5435 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 5436 static int iscsiGetUuid(void *pBackendData, PRTUUID pUuid) 5437 { 5438 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5439 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5440 int rc; 5441 5442 Assert(pImage); 5443 5444 if (pImage) 5445 rc = VERR_NOT_SUPPORTED; 5446 else 5447 rc = VERR_VD_NOT_OPENED; 5448 5449 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5450 return rc; 5451 } 5452 5453 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 5454 static int iscsiSetUuid(void *pBackendData, PCRTUUID pUuid) 5455 { 5456 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5457 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5458 int rc; 5459 5460 LogFlowFunc(("%RTuuid\n", pUuid)); 5461 Assert(pImage); 5462 5463 if (pImage) 5464 { 5465 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5466 rc = VERR_NOT_SUPPORTED; 5467 else 5468 rc = VERR_VD_IMAGE_READ_ONLY; 5469 } 5470 else 5471 rc = VERR_VD_NOT_OPENED; 5472 5473 LogFlowFunc(("returns %Rrc\n", rc)); 5474 return rc; 5475 } 5476 5477 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 5478 static int iscsiGetModificationUuid(void *pBackendData, PRTUUID pUuid) 5479 { 5480 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5481 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5482 int rc; 5483 5484 Assert(pImage); 5485 5486 if (pImage) 5487 rc = VERR_NOT_SUPPORTED; 5488 else 5489 rc = VERR_VD_NOT_OPENED; 5490 5491 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5492 return rc; 5493 } 5494 5495 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 5496 static int iscsiSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 5497 { 5498 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5499 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5500 int rc; 5501 5502 LogFlowFunc(("%RTuuid\n", pUuid)); 5503 Assert(pImage); 5504 5505 if (pImage) 5506 { 5507 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5508 rc = VERR_NOT_SUPPORTED; 5509 else 5510 rc = VERR_VD_IMAGE_READ_ONLY; 5511 } 5512 else 5513 rc = VERR_VD_NOT_OPENED; 5514 5515 LogFlowFunc(("returns %Rrc\n", rc)); 5516 return rc; 5517 } 5518 5519 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 5520 static int iscsiGetParentUuid(void *pBackendData, PRTUUID pUuid) 5521 { 5522 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5523 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5524 int rc; 5525 5526 Assert(pImage); 5527 5528 if (pImage) 5529 rc = VERR_NOT_SUPPORTED; 5530 else 5531 rc = VERR_VD_NOT_OPENED; 5532 5533 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5534 return rc; 5535 } 5536 5537 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 5538 static int iscsiSetParentUuid(void *pBackendData, PCRTUUID pUuid) 5539 { 5540 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5541 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5542 int rc; 5543 5544 LogFlowFunc(("%RTuuid\n", pUuid)); 5545 Assert(pImage); 5546 5547 if (pImage) 5548 { 5549 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5550 rc = VERR_NOT_SUPPORTED; 5551 else 5552 rc = VERR_VD_IMAGE_READ_ONLY; 5553 } 5554 else 5555 rc = VERR_VD_NOT_OPENED; 5556 5557 LogFlowFunc(("returns %Rrc\n", rc)); 5558 return rc; 5559 } 5560 5561 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 5562 static int iscsiGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 5563 { 5564 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 5565 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5566 int rc; 5567 5568 Assert(pImage); 5569 5570 if (pImage) 5571 rc = VERR_NOT_SUPPORTED; 5572 else 5573 rc = VERR_VD_NOT_OPENED; 5574 5575 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 5576 return rc; 5577 } 5578 5579 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 5580 static int iscsiSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 5581 { 5582 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 5583 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5584 int rc; 5585 5586 LogFlowFunc(("%RTuuid\n", pUuid)); 5587 Assert(pImage); 5588 5589 if (pImage) 5590 { 5591 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5592 rc = VERR_NOT_SUPPORTED; 5593 else 5594 rc = VERR_VD_IMAGE_READ_ONLY; 5595 } 5596 else 5597 rc = VERR_VD_NOT_OPENED; 5598 5599 LogFlowFunc(("returns %Rrc\n", rc)); 5600 return rc; 5601 } 5602 5603 /** @copydoc VBOXHDDBACKEND::pfnDump */ 5604 static void iscsiDump(void *pBackendData) 5605 { 5606 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5607 5608 Assert(pImage); 5609 if (pImage) 5610 { 5611 /** @todo put something useful here */ 5612 vdIfErrorMessage(pImage->pIfError, "Header: cVolume=%u\n", pImage->cVolume); 5613 } 5618 5614 } 5619 5615 … … 5705 5701 /* pfnFlush */ 5706 5702 iscsiFlush, 5703 /* pfnDiscard */ 5704 NULL, 5707 5705 /* pfnGetVersion */ 5708 5706 iscsiGetVersion, … … 5757 5755 /* pfnSetParentFilename */ 5758 5756 NULL, 5759 /* pfnAsyncRead */5760 iscsiAsyncRead,5761 /* pfnAsyncWrite */5762 iscsiAsyncWrite,5763 /* pfnAsyncFlush */5764 iscsiAsyncFlush,5765 5757 /* pfnComposeLocation */ 5766 5758 iscsiComposeLocation, … … 5771 5763 /* pfnResize */ 5772 5764 NULL, 5773 /* pfnDiscard */5774 NULL,5775 /* pfnAsyncDiscard */5776 NULL,5777 5765 /* pfnRepair */ 5778 5766 NULL -
trunk/src/VBox/Storage/Parallels.cpp
r44233 r44252 602 602 603 603 /** @copydoc VBOXHDDBACKEND::pfnRead */ 604 static int parallelsRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 605 size_t cbToRead, size_t *pcbActuallyRead) 606 { 607 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 608 pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 609 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 604 static int parallelsRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 605 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 606 { 607 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 608 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 610 609 int rc = VINF_SUCCESS; 610 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 611 uint64_t uSector; 612 uint64_t uOffsetInFile; 613 uint32_t iIndexInAllocationTable; 611 614 612 615 AssertPtr(pImage); … … 615 618 616 619 if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED) 617 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, cbToRead); 618 else 619 { 620 uint64_t uSector; 621 uint32_t iIndexInAllocationTable; 622 623 /* Calculate offset in the real file. */ 624 uSector = uOffset / 512; 625 626 /* One chunk in the file is always one track big. */ 627 iIndexInAllocationTable = (uint32_t)(uSector / pImage->PCHSGeometry.cSectors); 628 uSector = uSector % pImage->PCHSGeometry.cSectors; 629 630 Assert(iIndexInAllocationTable < pImage->cAllocationBitmapEntries); 631 632 cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512); 633 634 LogFlowFunc(("AllocationBitmap[%u]=%u uSector=%u cbToRead=%zu cAllocationBitmapEntries=%u\n", 635 iIndexInAllocationTable, pImage->pAllocationBitmap[iIndexInAllocationTable], 636 uSector, cbToRead, pImage->cAllocationBitmapEntries)); 637 638 if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0) 639 rc = VERR_VD_BLOCK_FREE; 640 else 641 { 642 uint64_t uOffsetInFile = ((uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512; 643 644 LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile)); 645 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffsetInFile, 646 pvBuf, cbToRead); 647 } 648 } 649 650 if ( ( RT_SUCCESS(rc) 651 || rc == VERR_VD_BLOCK_FREE) 652 && pcbActuallyRead) 653 *pcbActuallyRead = cbToRead; 654 655 LogFlowFunc(("returns %Rrc\n", rc)); 656 return rc; 657 } 658 659 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 660 static int parallelsWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 661 size_t cbToWrite, size_t *pcbWriteProcess, 662 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 663 { 664 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n", 665 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess)); 666 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 667 int rc = VINF_SUCCESS; 668 669 AssertPtr(pImage); 670 Assert(uOffset % 512 == 0); 671 Assert(cbToWrite % 512 == 0); 672 673 if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED) 674 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffset, 675 pvBuf, cbToWrite); 676 else 677 { 678 uint64_t uSector; 679 uint64_t uOffsetInFile; 680 uint32_t iIndexInAllocationTable; 681 620 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset, 621 pIoCtx, cbToRead); 622 else 623 { 682 624 /* Calculate offset in the real file. */ 683 625 uSector = uOffset / 512; … … 686 628 uSector = uSector % pImage->PCHSGeometry.cSectors; 687 629 688 Assert(iIndexInAllocationTable < pImage->cAllocationBitmapEntries); 689 690 cbToWrite = RT_MIN(cbToWrite, (pImage->PCHSGeometry.cSectors - uSector)*512); 691 692 LogFlowFunc(("AllocationBitmap[%u]=%u uSector=%u cbToWrite=%zu cAllocationBitmapEntries=%u\n", 693 iIndexInAllocationTable, pImage->pAllocationBitmap[iIndexInAllocationTable], 694 uSector, cbToWrite, pImage->cAllocationBitmapEntries)); 630 cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512); 695 631 696 632 if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0) 697 {698 if ( cbToWrite == pImage->PCHSGeometry.cSectors * 512699 && !(fWrite & VD_WRITE_NO_ALLOC))700 {701 /* Stay on the safe side. Do not run the risk of confusing the higher702 * level, as that can be pretty lethal to image consistency. */703 *pcbPreRead = 0;704 *pcbPostRead = 0;705 706 /* Allocate new chunk in the file. */707 AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));708 pImage->pAllocationBitmap[iIndexInAllocationTable] = (uint32_t)(pImage->cbFileCurrent / 512);709 pImage->cbFileCurrent += pImage->PCHSGeometry.cSectors * 512;710 pImage->fAllocationBitmapChanged = true;711 712 uOffsetInFile = (uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] * 512;713 714 LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));715 716 /*717 * Write the new block at the current end of the file.718 */719 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,720 uOffsetInFile, pvBuf, cbToWrite);721 }722 else723 {724 /* Trying to do a partial write to an unallocated cluster. Don't do725 * anything except letting the upper layer know what to do. */726 *pcbPreRead = uSector * 512;727 *pcbPostRead = (pImage->PCHSGeometry.cSectors * 512) - cbToWrite - *pcbPreRead;728 rc = VERR_VD_BLOCK_FREE;729 }730 }731 else732 {733 uOffsetInFile = ((uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;734 735 LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));736 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffsetInFile,737 pvBuf, cbToWrite);738 }739 }740 741 if (pcbWriteProcess)742 *pcbWriteProcess = cbToWrite;743 744 out:745 LogFlowFunc(("returns %Rrc\n", rc));746 return rc;747 }748 749 /** @copydoc VBOXHDDBACKEND::pfnFlush */750 static int parallelsFlush(void *pBackendData)751 {752 LogFlowFunc(("pBackendData=%#p\n", pBackendData));753 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;754 int rc;755 756 AssertPtr(pImage);757 758 rc = parallelsFlushImage(pImage);759 760 LogFlowFunc(("returns %Rrc\n", rc));761 return rc;762 }763 764 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */765 static unsigned parallelsGetVersion(void *pBackendData)766 {767 LogFlowFunc(("pBackendData=%#p\n", pBackendData));768 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;769 770 AssertPtr(pImage);771 772 if (pImage)773 return PARALLELS_DISK_VERSION;774 else775 return 0;776 }777 778 /** @copydoc VBOXHDDBACKEND::pfnGetSize */779 static uint64_t parallelsGetSize(void *pBackendData)780 {781 LogFlowFunc(("pBackendData=%#p\n", pBackendData));782 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;783 uint64_t cb = 0;784 785 AssertPtr(pImage);786 787 if (pImage && pImage->pStorage)788 cb = pImage->cbSize;789 790 LogFlowFunc(("returns %llu\n", cb));791 return cb;792 }793 794 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */795 static uint64_t parallelsGetFileSize(void *pBackendData)796 {797 LogFlowFunc(("pBackendData=%#p\n", pBackendData));798 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;799 uint64_t cb = 0;800 801 AssertPtr(pImage);802 803 if (pImage && pImage->pStorage)804 cb = pImage->cbFileCurrent;805 806 LogFlowFunc(("returns %lld\n", cb));807 return cb;808 }809 810 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */811 static int parallelsGetPCHSGeometry(void *pBackendData,812 PVDGEOMETRY pPCHSGeometry)813 {814 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));815 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;816 int rc;817 818 AssertPtr(pImage);819 820 if (pImage)821 {822 if (pImage->PCHSGeometry.cCylinders)823 {824 *pPCHSGeometry = pImage->PCHSGeometry;825 rc = VINF_SUCCESS;826 }827 else828 rc = VERR_VD_GEOMETRY_NOT_SET;829 }830 else831 rc = VERR_VD_NOT_OPENED;832 833 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));834 return rc;835 }836 837 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */838 static int parallelsSetPCHSGeometry(void *pBackendData,839 PCVDGEOMETRY pPCHSGeometry)840 {841 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));842 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;843 int rc;844 845 AssertPtr(pImage);846 847 if (pImage)848 {849 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)850 {851 rc = VERR_VD_IMAGE_READ_ONLY;852 goto out;853 }854 855 pImage->PCHSGeometry = *pPCHSGeometry;856 rc = VINF_SUCCESS;857 }858 else859 rc = VERR_VD_NOT_OPENED;860 861 out:862 LogFlowFunc(("returns %Rrc\n", rc));863 return rc;864 }865 866 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */867 static int parallelsGetLCHSGeometry(void *pBackendData,868 PVDGEOMETRY pLCHSGeometry)869 {870 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));871 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;872 int rc;873 874 AssertPtr(pImage);875 876 if (pImage)877 {878 if (pImage->LCHSGeometry.cCylinders)879 {880 *pLCHSGeometry = pImage->LCHSGeometry;881 rc = VINF_SUCCESS;882 }883 else884 rc = VERR_VD_GEOMETRY_NOT_SET;885 }886 else887 rc = VERR_VD_NOT_OPENED;888 889 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));890 return rc;891 }892 893 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */894 static int parallelsSetLCHSGeometry(void *pBackendData,895 PCVDGEOMETRY pLCHSGeometry)896 {897 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));898 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;899 int rc;900 901 AssertPtr(pImage);902 903 if (pImage)904 {905 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)906 {907 rc = VERR_VD_IMAGE_READ_ONLY;908 goto out;909 }910 911 pImage->LCHSGeometry = *pLCHSGeometry;912 rc = VINF_SUCCESS;913 }914 else915 rc = VERR_VD_NOT_OPENED;916 917 out:918 LogFlowFunc(("returns %Rrc\n", rc));919 return rc;920 }921 922 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */923 static unsigned parallelsGetImageFlags(void *pBackendData)924 {925 LogFlowFunc(("pBackendData=%#p\n", pBackendData));926 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;927 unsigned uImageFlags;928 929 AssertPtr(pImage);930 931 if (pImage)932 uImageFlags = pImage->uImageFlags;933 else934 uImageFlags = 0;935 936 LogFlowFunc(("returns %#x\n", uImageFlags));937 return uImageFlags;938 }939 940 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */941 static unsigned parallelsGetOpenFlags(void *pBackendData)942 {943 LogFlowFunc(("pBackendData=%#p\n", pBackendData));944 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;945 unsigned uOpenFlags;946 947 AssertPtr(pImage);948 949 if (pImage)950 uOpenFlags = pImage->uOpenFlags;951 else952 uOpenFlags = 0;953 954 LogFlowFunc(("returns %#x\n", uOpenFlags));955 return uOpenFlags;956 }957 958 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */959 static int parallelsSetOpenFlags(void *pBackendData, unsigned uOpenFlags)960 {961 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));962 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;963 int rc;964 965 /* Image must be opened and the new flags must be valid. */966 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO967 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE968 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))969 {970 rc = VERR_INVALID_PARAMETER;971 goto out;972 }973 974 /* Implement this operation via reopening the image. */975 parallelsFreeImage(pImage, false);976 rc = parallelsOpenImage(pImage, uOpenFlags);977 978 out:979 LogFlowFunc(("returns %Rrc\n", rc));980 return rc;981 }982 983 /** @copydoc VBOXHDDBACKEND::pfnGetComment */984 static int parallelsGetComment(void *pBackendData, char *pszComment,985 size_t cbComment)986 {987 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));988 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;989 int rc;990 991 AssertPtr(pImage);992 993 if (pImage)994 rc = VERR_NOT_SUPPORTED;995 else996 rc = VERR_VD_NOT_OPENED;997 998 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));999 return rc;1000 }1001 1002 /** @copydoc VBOXHDDBACKEND::pfnSetComment */1003 static int parallelsSetComment(void *pBackendData, const char *pszComment)1004 {1005 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));1006 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1007 int rc;1008 1009 AssertPtr(pImage);1010 1011 if (pImage)1012 {1013 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)1014 rc = VERR_VD_IMAGE_READ_ONLY;1015 else1016 rc = VERR_NOT_SUPPORTED;1017 }1018 else1019 rc = VERR_VD_NOT_OPENED;1020 1021 LogFlowFunc(("returns %Rrc\n", rc));1022 return rc;1023 }1024 1025 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */1026 static int parallelsGetUuid(void *pBackendData, PRTUUID pUuid)1027 {1028 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));1029 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1030 int rc;1031 1032 AssertPtr(pImage);1033 1034 if (pImage)1035 rc = VERR_NOT_SUPPORTED;1036 else1037 rc = VERR_VD_NOT_OPENED;1038 1039 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));1040 return rc;1041 }1042 1043 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */1044 static int parallelsSetUuid(void *pBackendData, PCRTUUID pUuid)1045 {1046 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));1047 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1048 int rc;1049 1050 AssertPtr(pImage);1051 1052 if (pImage)1053 {1054 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))1055 rc = VERR_NOT_SUPPORTED;1056 else1057 rc = VERR_VD_IMAGE_READ_ONLY;1058 }1059 else1060 rc = VERR_VD_NOT_OPENED;1061 1062 LogFlowFunc(("returns %Rrc\n", rc));1063 return rc;1064 }1065 1066 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */1067 static int parallelsGetModificationUuid(void *pBackendData, PRTUUID pUuid)1068 {1069 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));1070 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1071 int rc;1072 1073 AssertPtr(pImage);1074 1075 if (pImage)1076 rc = VERR_NOT_SUPPORTED;1077 else1078 rc = VERR_VD_NOT_OPENED;1079 1080 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));1081 return rc;1082 }1083 1084 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */1085 static int parallelsSetModificationUuid(void *pBackendData, PCRTUUID pUuid)1086 {1087 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));1088 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1089 int rc;1090 1091 AssertPtr(pImage);1092 1093 if (pImage)1094 {1095 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))1096 rc = VERR_NOT_SUPPORTED;1097 else1098 rc = VERR_VD_IMAGE_READ_ONLY;1099 }1100 else1101 rc = VERR_VD_NOT_OPENED;1102 1103 LogFlowFunc(("returns %Rrc\n", rc));1104 return rc;1105 }1106 1107 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */1108 static int parallelsGetParentUuid(void *pBackendData, PRTUUID pUuid)1109 {1110 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));1111 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1112 int rc;1113 1114 AssertPtr(pImage);1115 1116 if (pImage)1117 rc = VERR_NOT_SUPPORTED;1118 else1119 rc = VERR_VD_NOT_OPENED;1120 1121 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));1122 return rc;1123 }1124 1125 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */1126 static int parallelsSetParentUuid(void *pBackendData, PCRTUUID pUuid)1127 {1128 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));1129 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1130 int rc;1131 1132 AssertPtr(pImage);1133 1134 if (pImage)1135 {1136 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))1137 rc = VERR_NOT_SUPPORTED;1138 else1139 rc = VERR_VD_IMAGE_READ_ONLY;1140 }1141 else1142 rc = VERR_VD_NOT_OPENED;1143 1144 LogFlowFunc(("returns %Rrc\n", rc));1145 return rc;1146 }1147 1148 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */1149 static int parallelsGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)1150 {1151 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));1152 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1153 int rc;1154 1155 AssertPtr(pImage);1156 1157 if (pImage)1158 rc = VERR_NOT_SUPPORTED;1159 else1160 rc = VERR_VD_NOT_OPENED;1161 1162 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));1163 return rc;1164 }1165 1166 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */1167 static int parallelsSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)1168 {1169 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));1170 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1171 int rc;1172 1173 AssertPtr(pImage);1174 1175 if (pImage)1176 {1177 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))1178 rc = VERR_NOT_SUPPORTED;1179 else1180 rc = VERR_VD_IMAGE_READ_ONLY;1181 }1182 else1183 rc = VERR_VD_NOT_OPENED;1184 1185 LogFlowFunc(("returns %Rrc\n", rc));1186 return rc;1187 }1188 1189 /** @copydoc VBOXHDDBACKEND::pfnDump */1190 static void parallelsDump(void *pBackendData)1191 {1192 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1193 1194 AssertPtr(pImage);1195 if (pImage)1196 {1197 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n",1198 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,1199 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors);1200 }1201 }1202 1203 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */1204 static int parallelsAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,1205 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)1206 {1207 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",1208 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));1209 int rc = VINF_SUCCESS;1210 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;1211 uint64_t uSector;1212 uint64_t uOffsetInFile;1213 uint32_t iIndexInAllocationTable;1214 1215 AssertPtr(pImage);1216 Assert(uOffset % 512 == 0);1217 Assert(cbToRead % 512 == 0);1218 1219 if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)1220 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,1221 pIoCtx, cbToRead);1222 else1223 {1224 /* Calculate offset in the real file. */1225 uSector = uOffset / 512;1226 /* One chunk in the file is always one track big. */1227 iIndexInAllocationTable = (uint32_t)(uSector / pImage->PCHSGeometry.cSectors);1228 uSector = uSector % pImage->PCHSGeometry.cSectors;1229 1230 cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);1231 1232 if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)1233 {1234 633 rc = VERR_VD_BLOCK_FREE; 1235 }1236 634 else 1237 635 { … … 1248 646 } 1249 647 1250 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 1251 static int parallelsAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 1252 PVDIOCTX pIoCtx, 1253 size_t *pcbWriteProcess, size_t *pcbPreRead, 1254 size_t *pcbPostRead, unsigned fWrite) 648 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 649 static int parallelsWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 650 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 651 size_t *pcbPostRead, unsigned fWrite) 1255 652 { 1256 653 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p\n", … … 1333 730 } 1334 731 1335 /** @copydoc VBOXHDDBACKEND::pfn AsyncFlush */1336 static int parallels AsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)732 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 733 static int parallelsFlush(void *pBackendData, PVDIOCTX pIoCtx) 1337 734 { 1338 735 int rc = VINF_SUCCESS; … … 1347 744 return rc; 1348 745 } 746 747 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 748 static unsigned parallelsGetVersion(void *pBackendData) 749 { 750 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 751 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 752 753 AssertPtr(pImage); 754 755 if (pImage) 756 return PARALLELS_DISK_VERSION; 757 else 758 return 0; 759 } 760 761 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 762 static uint64_t parallelsGetSize(void *pBackendData) 763 { 764 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 765 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 766 uint64_t cb = 0; 767 768 AssertPtr(pImage); 769 770 if (pImage && pImage->pStorage) 771 cb = pImage->cbSize; 772 773 LogFlowFunc(("returns %llu\n", cb)); 774 return cb; 775 } 776 777 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 778 static uint64_t parallelsGetFileSize(void *pBackendData) 779 { 780 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 781 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 782 uint64_t cb = 0; 783 784 AssertPtr(pImage); 785 786 if (pImage && pImage->pStorage) 787 cb = pImage->cbFileCurrent; 788 789 LogFlowFunc(("returns %lld\n", cb)); 790 return cb; 791 } 792 793 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 794 static int parallelsGetPCHSGeometry(void *pBackendData, 795 PVDGEOMETRY pPCHSGeometry) 796 { 797 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 798 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 799 int rc; 800 801 AssertPtr(pImage); 802 803 if (pImage) 804 { 805 if (pImage->PCHSGeometry.cCylinders) 806 { 807 *pPCHSGeometry = pImage->PCHSGeometry; 808 rc = VINF_SUCCESS; 809 } 810 else 811 rc = VERR_VD_GEOMETRY_NOT_SET; 812 } 813 else 814 rc = VERR_VD_NOT_OPENED; 815 816 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 817 return rc; 818 } 819 820 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 821 static int parallelsSetPCHSGeometry(void *pBackendData, 822 PCVDGEOMETRY pPCHSGeometry) 823 { 824 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 825 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 826 int rc; 827 828 AssertPtr(pImage); 829 830 if (pImage) 831 { 832 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 833 { 834 rc = VERR_VD_IMAGE_READ_ONLY; 835 goto out; 836 } 837 838 pImage->PCHSGeometry = *pPCHSGeometry; 839 rc = VINF_SUCCESS; 840 } 841 else 842 rc = VERR_VD_NOT_OPENED; 843 844 out: 845 LogFlowFunc(("returns %Rrc\n", rc)); 846 return rc; 847 } 848 849 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 850 static int parallelsGetLCHSGeometry(void *pBackendData, 851 PVDGEOMETRY pLCHSGeometry) 852 { 853 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 854 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 855 int rc; 856 857 AssertPtr(pImage); 858 859 if (pImage) 860 { 861 if (pImage->LCHSGeometry.cCylinders) 862 { 863 *pLCHSGeometry = pImage->LCHSGeometry; 864 rc = VINF_SUCCESS; 865 } 866 else 867 rc = VERR_VD_GEOMETRY_NOT_SET; 868 } 869 else 870 rc = VERR_VD_NOT_OPENED; 871 872 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 873 return rc; 874 } 875 876 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 877 static int parallelsSetLCHSGeometry(void *pBackendData, 878 PCVDGEOMETRY pLCHSGeometry) 879 { 880 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 881 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 882 int rc; 883 884 AssertPtr(pImage); 885 886 if (pImage) 887 { 888 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 889 { 890 rc = VERR_VD_IMAGE_READ_ONLY; 891 goto out; 892 } 893 894 pImage->LCHSGeometry = *pLCHSGeometry; 895 rc = VINF_SUCCESS; 896 } 897 else 898 rc = VERR_VD_NOT_OPENED; 899 900 out: 901 LogFlowFunc(("returns %Rrc\n", rc)); 902 return rc; 903 } 904 905 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 906 static unsigned parallelsGetImageFlags(void *pBackendData) 907 { 908 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 909 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 910 unsigned uImageFlags; 911 912 AssertPtr(pImage); 913 914 if (pImage) 915 uImageFlags = pImage->uImageFlags; 916 else 917 uImageFlags = 0; 918 919 LogFlowFunc(("returns %#x\n", uImageFlags)); 920 return uImageFlags; 921 } 922 923 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 924 static unsigned parallelsGetOpenFlags(void *pBackendData) 925 { 926 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 927 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 928 unsigned uOpenFlags; 929 930 AssertPtr(pImage); 931 932 if (pImage) 933 uOpenFlags = pImage->uOpenFlags; 934 else 935 uOpenFlags = 0; 936 937 LogFlowFunc(("returns %#x\n", uOpenFlags)); 938 return uOpenFlags; 939 } 940 941 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 942 static int parallelsSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 943 { 944 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 945 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 946 int rc; 947 948 /* Image must be opened and the new flags must be valid. */ 949 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 950 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE 951 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 952 { 953 rc = VERR_INVALID_PARAMETER; 954 goto out; 955 } 956 957 /* Implement this operation via reopening the image. */ 958 parallelsFreeImage(pImage, false); 959 rc = parallelsOpenImage(pImage, uOpenFlags); 960 961 out: 962 LogFlowFunc(("returns %Rrc\n", rc)); 963 return rc; 964 } 965 966 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 967 static int parallelsGetComment(void *pBackendData, char *pszComment, 968 size_t cbComment) 969 { 970 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 971 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 972 int rc; 973 974 AssertPtr(pImage); 975 976 if (pImage) 977 rc = VERR_NOT_SUPPORTED; 978 else 979 rc = VERR_VD_NOT_OPENED; 980 981 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 982 return rc; 983 } 984 985 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 986 static int parallelsSetComment(void *pBackendData, const char *pszComment) 987 { 988 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 989 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 990 int rc; 991 992 AssertPtr(pImage); 993 994 if (pImage) 995 { 996 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 997 rc = VERR_VD_IMAGE_READ_ONLY; 998 else 999 rc = VERR_NOT_SUPPORTED; 1000 } 1001 else 1002 rc = VERR_VD_NOT_OPENED; 1003 1004 LogFlowFunc(("returns %Rrc\n", rc)); 1005 return rc; 1006 } 1007 1008 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 1009 static int parallelsGetUuid(void *pBackendData, PRTUUID pUuid) 1010 { 1011 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1012 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1013 int rc; 1014 1015 AssertPtr(pImage); 1016 1017 if (pImage) 1018 rc = VERR_NOT_SUPPORTED; 1019 else 1020 rc = VERR_VD_NOT_OPENED; 1021 1022 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 1023 return rc; 1024 } 1025 1026 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 1027 static int parallelsSetUuid(void *pBackendData, PCRTUUID pUuid) 1028 { 1029 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1030 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1031 int rc; 1032 1033 AssertPtr(pImage); 1034 1035 if (pImage) 1036 { 1037 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1038 rc = VERR_NOT_SUPPORTED; 1039 else 1040 rc = VERR_VD_IMAGE_READ_ONLY; 1041 } 1042 else 1043 rc = VERR_VD_NOT_OPENED; 1044 1045 LogFlowFunc(("returns %Rrc\n", rc)); 1046 return rc; 1047 } 1048 1049 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 1050 static int parallelsGetModificationUuid(void *pBackendData, PRTUUID pUuid) 1051 { 1052 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1053 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1054 int rc; 1055 1056 AssertPtr(pImage); 1057 1058 if (pImage) 1059 rc = VERR_NOT_SUPPORTED; 1060 else 1061 rc = VERR_VD_NOT_OPENED; 1062 1063 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 1064 return rc; 1065 } 1066 1067 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 1068 static int parallelsSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 1069 { 1070 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1071 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1072 int rc; 1073 1074 AssertPtr(pImage); 1075 1076 if (pImage) 1077 { 1078 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1079 rc = VERR_NOT_SUPPORTED; 1080 else 1081 rc = VERR_VD_IMAGE_READ_ONLY; 1082 } 1083 else 1084 rc = VERR_VD_NOT_OPENED; 1085 1086 LogFlowFunc(("returns %Rrc\n", rc)); 1087 return rc; 1088 } 1089 1090 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 1091 static int parallelsGetParentUuid(void *pBackendData, PRTUUID pUuid) 1092 { 1093 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1094 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1095 int rc; 1096 1097 AssertPtr(pImage); 1098 1099 if (pImage) 1100 rc = VERR_NOT_SUPPORTED; 1101 else 1102 rc = VERR_VD_NOT_OPENED; 1103 1104 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 1105 return rc; 1106 } 1107 1108 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 1109 static int parallelsSetParentUuid(void *pBackendData, PCRTUUID pUuid) 1110 { 1111 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1112 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1113 int rc; 1114 1115 AssertPtr(pImage); 1116 1117 if (pImage) 1118 { 1119 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1120 rc = VERR_NOT_SUPPORTED; 1121 else 1122 rc = VERR_VD_IMAGE_READ_ONLY; 1123 } 1124 else 1125 rc = VERR_VD_NOT_OPENED; 1126 1127 LogFlowFunc(("returns %Rrc\n", rc)); 1128 return rc; 1129 } 1130 1131 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 1132 static int parallelsGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 1133 { 1134 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1135 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1136 int rc; 1137 1138 AssertPtr(pImage); 1139 1140 if (pImage) 1141 rc = VERR_NOT_SUPPORTED; 1142 else 1143 rc = VERR_VD_NOT_OPENED; 1144 1145 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 1146 return rc; 1147 } 1148 1149 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 1150 static int parallelsSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 1151 { 1152 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1153 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1154 int rc; 1155 1156 AssertPtr(pImage); 1157 1158 if (pImage) 1159 { 1160 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1161 rc = VERR_NOT_SUPPORTED; 1162 else 1163 rc = VERR_VD_IMAGE_READ_ONLY; 1164 } 1165 else 1166 rc = VERR_VD_NOT_OPENED; 1167 1168 LogFlowFunc(("returns %Rrc\n", rc)); 1169 return rc; 1170 } 1171 1172 /** @copydoc VBOXHDDBACKEND::pfnDump */ 1173 static void parallelsDump(void *pBackendData) 1174 { 1175 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1176 1177 AssertPtr(pImage); 1178 if (pImage) 1179 { 1180 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n", 1181 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 1182 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors); 1183 } 1184 } 1185 1349 1186 1350 1187 … … 1379 1216 /* pfnFlush */ 1380 1217 parallelsFlush, 1218 /* pfnDiscard */ 1219 NULL, 1381 1220 /* pfnGetVersion */ 1382 1221 parallelsGetVersion, … … 1431 1270 /* pfnSetParentFilename */ 1432 1271 NULL, 1433 /* pfnAsyncRead */1434 parallelsAsyncRead,1435 /* pfnAsyncWrite */1436 parallelsAsyncWrite,1437 /* pfnAsyncFlush */1438 parallelsAsyncFlush,1439 1272 /* pfnComposeLocation */ 1440 1273 genericFileComposeLocation, … … 1445 1278 /* pfnResize */ 1446 1279 NULL, 1447 /* pfnDiscard */1448 NULL,1449 /* pfnAsyncDiscard */1450 NULL,1451 1280 /* pfnRepair */ 1452 1281 NULL -
trunk/src/VBox/Storage/QCOW.cpp
r44233 r44252 684 684 * @returns VBox status code. 685 685 * @param pImage Image instance data. 686 * @param offL2Tbl The offset of the L2 table in the image.687 * @param ppL2Entry Where to store the L2 table on success.688 */689 static int qcowL2TblCacheFetch(PQCOWIMAGE pImage, uint64_t offL2Tbl, PQCOWL2CACHEENTRY *ppL2Entry)690 {691 int rc = VINF_SUCCESS;692 693 LogFlowFunc(("pImage=%#p offL2Tbl=%llu ppL2Entry=%#p\n", pImage, offL2Tbl, ppL2Entry));694 695 /* Try to fetch the L2 table from the cache first. */696 PQCOWL2CACHEENTRY pL2Entry = qcowL2TblCacheRetain(pImage, offL2Tbl);697 if (!pL2Entry)698 {699 LogFlowFunc(("Reading L2 table from image\n"));700 pL2Entry = qcowL2TblCacheEntryAlloc(pImage);701 702 if (pL2Entry)703 {704 /* Read from the image. */705 pL2Entry->offL2Tbl = offL2Tbl;706 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offL2Tbl,707 pL2Entry->paL2Tbl, pImage->cbL2Table);708 if (RT_SUCCESS(rc))709 {710 #if defined(RT_LITTLE_ENDIAN)711 qcowTableConvertToHostEndianess(pL2Entry->paL2Tbl, pImage->cL2TableEntries);712 #endif713 qcowL2TblCacheEntryInsert(pImage, pL2Entry);714 }715 else716 {717 qcowL2TblCacheEntryRelease(pL2Entry);718 qcowL2TblCacheEntryFree(pImage, pL2Entry);719 }720 }721 else722 rc = VERR_NO_MEMORY;723 }724 725 if (RT_SUCCESS(rc))726 *ppL2Entry = pL2Entry;727 728 LogFlowFunc(("returns rc=%Rrc\n", rc));729 return rc;730 }731 732 /**733 * Fetches the L2 from the given offset trying the LRU cache first and734 * reading it from the image after a cache miss - version for async I/O.735 *736 * @returns VBox status code.737 * @param pImage Image instance data.738 686 * @param pIoCtx The I/O context. 739 687 * @param offL2Tbl The offset of the L2 table in the image. 740 688 * @param ppL2Entry Where to store the L2 table on success. 741 689 */ 742 static int qcowL2TblCacheFetch Async(PQCOWIMAGE pImage, PVDIOCTX pIoCtx,743 uint64_t offL2Tbl,PQCOWL2CACHEENTRY *ppL2Entry)690 static int qcowL2TblCacheFetch(PQCOWIMAGE pImage, PVDIOCTX pIoCtx, uint64_t offL2Tbl, 691 PQCOWL2CACHEENTRY *ppL2Entry) 744 692 { 745 693 int rc = VINF_SUCCESS; … … 876 824 * VERR_VD_BLOCK_FREE if the cluster is not yet allocated. 877 825 * @param pImage The image instance data. 878 * @param idxL1 The L1 index.879 * @param idxL2 The L2 index.880 * @param offCluster Offset inside the cluster.881 * @param poffImage Where to store the image offset on success;882 */883 static int qcowConvertToImageOffset(PQCOWIMAGE pImage, uint32_t idxL1, uint32_t idxL2,884 uint32_t offCluster, uint64_t *poffImage)885 {886 int rc = VERR_VD_BLOCK_FREE;887 LogFlowFunc(("pImage=%#p idxL1=%u idxL2=%u offCluster=%u poffImage=%#p\n",888 pImage, idxL1, idxL2, offCluster, poffImage));889 890 AssertReturn(idxL1 < pImage->cL1TableEntries, VERR_INVALID_PARAMETER);891 AssertReturn(idxL2 < pImage->cL2TableEntries, VERR_INVALID_PARAMETER);892 893 if (pImage->paL1Table[idxL1])894 {895 PQCOWL2CACHEENTRY pL2Entry;896 897 rc = qcowL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);898 if (RT_SUCCESS(rc))899 {900 LogFlowFunc(("cluster start offset %llu\n", pL2Entry->paL2Tbl[idxL2]));901 /* Get real file offset. */902 if (pL2Entry->paL2Tbl[idxL2])903 {904 uint64_t off = pL2Entry->paL2Tbl[idxL2];905 906 /* Strip flags */907 if (pImage->uVersion == 2)908 {909 if (RT_UNLIKELY(off & QCOW_V2_COMPRESSED_FLAG))910 rc = VERR_NOT_SUPPORTED;911 else912 off &= ~(QCOW_V2_COMPRESSED_FLAG | QCOW_V2_COPIED_FLAG);913 }914 else915 {916 if (RT_UNLIKELY(off & QCOW_V1_COMPRESSED_FLAG))917 rc = VERR_NOT_SUPPORTED;918 else919 off &= ~QCOW_V1_COMPRESSED_FLAG;920 }921 922 *poffImage = off + offCluster;923 }924 else925 rc = VERR_VD_BLOCK_FREE;926 927 qcowL2TblCacheEntryRelease(pL2Entry);928 }929 }930 931 LogFlowFunc(("returns rc=%Rrc\n", rc));932 return rc;933 }934 935 /**936 * Returns the real image offset for a given cluster or an error if the cluster is not937 * yet allocated- version for async I/O.938 *939 * @returns VBox status code.940 * VERR_VD_BLOCK_FREE if the cluster is not yet allocated.941 * @param pImage The image instance data.942 826 * @param pIoCtx The I/O context. 943 827 * @param idxL1 The L1 index. … … 946 830 * @param poffImage Where to store the image offset on success; 947 831 */ 948 static int qcowConvertToImageOffset Async(PQCOWIMAGE pImage, PVDIOCTX pIoCtx,949 950 832 static int qcowConvertToImageOffset(PQCOWIMAGE pImage, PVDIOCTX pIoCtx, 833 uint32_t idxL1, uint32_t idxL2, 834 uint32_t offCluster, uint64_t *poffImage) 951 835 { 952 836 int rc = VERR_VD_BLOCK_FREE; … … 959 843 PQCOWL2CACHEENTRY pL2Entry; 960 844 961 rc = qcowL2TblCacheFetchAsync(pImage, pIoCtx, pImage->paL1Table[idxL1], 962 &pL2Entry); 845 rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1], &pL2Entry); 963 846 if (RT_SUCCESS(rc)) 964 847 { … … 1787 1670 } 1788 1671 1789 /** @copydoc VBOXHDDBACKEND::pfnRead */ 1790 static int qcowRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 1791 size_t cbToRead, size_t *pcbActuallyRead) 1792 { 1793 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1794 pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 1672 static int qcowRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 1673 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1674 { 1675 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1676 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 1795 1677 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1796 1678 uint32_t offCluster = 0; … … 1804 1686 Assert(cbToRead % 512 == 0); 1805 1687 1688 if (!VALID_PTR(pIoCtx) || !cbToRead) 1689 { 1690 rc = VERR_INVALID_PARAMETER; 1691 goto out; 1692 } 1693 1806 1694 if ( uOffset + cbToRead > pImage->cbSize 1807 1695 || cbToRead == 0) … … 1812 1700 1813 1701 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 1814 LogFlowFunc(("idxL1=%u idxL2=%u offCluster=%u\n", idxL1, idxL2, offCluster));1815 1702 1816 1703 /* Clip read size to remain in the cluster. */ … … 1818 1705 1819 1706 /* Get offset in image. */ 1820 rc = qcowConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offFile); 1821 if (RT_SUCCESS(rc)) 1822 { 1823 LogFlowFunc(("offFile=%llu\n", offFile)); 1824 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offFile, 1825 pvBuf, cbToRead); 1826 } 1827 1828 if ( (RT_SUCCESS(rc) || rc == VERR_VD_BLOCK_FREE) 1829 && pcbActuallyRead) 1830 *pcbActuallyRead = cbToRead; 1831 1832 out: 1833 LogFlowFunc(("returns %Rrc\n", rc)); 1834 return rc; 1835 } 1836 1837 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1838 static int qcowWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 1839 size_t cbToWrite, size_t *pcbWriteProcess, 1840 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 1841 { 1842 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 1843 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 1844 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1845 uint32_t offCluster = 0; 1846 uint32_t idxL1 = 0; 1847 uint32_t idxL2 = 0; 1848 uint64_t offImage = 0; 1849 int rc; 1850 1851 AssertPtr(pImage); 1852 Assert(uOffset % 512 == 0); 1853 Assert(cbToWrite % 512 == 0); 1854 1855 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1856 { 1857 rc = VERR_VD_IMAGE_READ_ONLY; 1858 goto out; 1859 } 1860 1861 if ( uOffset + cbToWrite > pImage->cbSize 1862 || cbToWrite == 0) 1863 { 1864 rc = VERR_INVALID_PARAMETER; 1865 goto out; 1866 } 1867 1868 /* Convert offset to L1, L2 index and cluster offset. */ 1869 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 1870 1871 /* Clip write size to remain in the cluster. */ 1872 cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster); 1873 Assert(!(cbToWrite % 512)); 1874 1875 /* Get offset in image. */ 1876 rc = qcowConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offImage); 1877 if (RT_SUCCESS(rc)) 1878 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offImage, 1879 pvBuf, cbToWrite); 1880 else if (rc == VERR_VD_BLOCK_FREE) 1881 { 1882 if ( cbToWrite == pImage->cbCluster 1883 && !(fWrite & VD_WRITE_NO_ALLOC)) 1884 { 1885 PQCOWL2CACHEENTRY pL2Entry = NULL; 1886 1887 /* Full cluster write to previously unallocated cluster. 1888 * Allocate cluster and write data. */ 1889 Assert(!offCluster); 1890 1891 do 1892 { 1893 uint64_t idxUpdateLe = 0; 1894 1895 /* Check if we have to allocate a new cluster for L2 tables. */ 1896 if (!pImage->paL1Table[idxL1]) 1897 { 1898 uint64_t offL2Tbl = qcowClusterAllocate(pImage, qcowByte2Cluster(pImage, pImage->cbL2Table)); 1899 1900 pL2Entry = qcowL2TblCacheEntryAlloc(pImage); 1901 if (!pL2Entry) 1902 { 1903 rc = VERR_NO_MEMORY; 1904 break; 1905 } 1906 1907 pL2Entry->offL2Tbl = offL2Tbl; 1908 memset(pL2Entry->paL2Tbl, 0, pImage->cbL2Table); 1909 qcowL2TblCacheEntryInsert(pImage, pL2Entry); 1910 1911 /* 1912 * Write the L2 table first and link to the L1 table afterwards. 1913 * If something unexpected happens the worst case which can happen 1914 * is a leak of some clusters. 1915 */ 1916 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offL2Tbl, 1917 pL2Entry->paL2Tbl, pImage->cbL2Table); 1918 if (RT_FAILURE(rc)) 1919 break; 1920 1921 /* Write the L1 link now. */ 1922 pImage->paL1Table[idxL1] = offL2Tbl; 1923 idxUpdateLe = RT_H2BE_U64(offL2Tbl); 1924 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1925 pImage->offL1Table + idxL1*sizeof(uint64_t), 1926 &idxUpdateLe, sizeof(uint64_t)); 1927 if (RT_FAILURE(rc)) 1928 break; 1929 } 1930 else 1931 rc = qcowL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry); 1932 1933 if (RT_SUCCESS(rc)) 1934 { 1935 /* Allocate new cluster for the data. */ 1936 uint64_t offData = qcowClusterAllocate(pImage, 1); 1937 1938 /* Write data. */ 1939 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1940 offData, pvBuf, cbToWrite); 1941 if (RT_FAILURE(rc)) 1942 break; 1943 1944 /* Link L2 table and update it. */ 1945 pL2Entry->paL2Tbl[idxL2] = offData; 1946 idxUpdateLe = RT_H2BE_U64(offData); 1947 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1948 pImage->paL1Table[idxL1] + idxL2*sizeof(uint64_t), 1949 &idxUpdateLe, sizeof(uint64_t)); 1950 qcowL2TblCacheEntryRelease(pL2Entry); 1951 } 1952 1953 } while (0); 1954 1955 *pcbPreRead = 0; 1956 *pcbPostRead = 0; 1957 } 1958 else 1959 { 1960 /* Trying to do a partial write to an unallocated cluster. Don't do 1961 * anything except letting the upper layer know what to do. */ 1962 *pcbPreRead = offCluster; 1963 *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead; 1964 } 1965 } 1966 1967 if (pcbWriteProcess) 1968 *pcbWriteProcess = cbToWrite; 1969 1970 out: 1971 LogFlowFunc(("returns %Rrc\n", rc)); 1972 return rc; 1973 } 1974 1975 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1976 static int qcowFlush(void *pBackendData) 1977 { 1978 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1979 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1980 int rc; 1981 1982 rc = qcowFlushImage(pImage); 1983 LogFlowFunc(("returns %Rrc\n", rc)); 1984 return rc; 1985 } 1986 1987 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 1988 static unsigned qcowGetVersion(void *pBackendData) 1989 { 1990 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1991 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1992 1993 AssertPtr(pImage); 1994 1995 if (pImage) 1996 return pImage->uVersion; 1997 else 1998 return 0; 1999 } 2000 2001 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 2002 static uint64_t qcowGetSize(void *pBackendData) 2003 { 2004 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2005 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2006 uint64_t cb = 0; 2007 2008 AssertPtr(pImage); 2009 2010 if (pImage && pImage->pStorage) 2011 cb = pImage->cbSize; 2012 2013 LogFlowFunc(("returns %llu\n", cb)); 2014 return cb; 2015 } 2016 2017 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 2018 static uint64_t qcowGetFileSize(void *pBackendData) 2019 { 2020 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2021 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2022 uint64_t cb = 0; 2023 2024 AssertPtr(pImage); 2025 2026 if (pImage) 2027 { 2028 uint64_t cbFile; 2029 if (pImage->pStorage) 2030 { 2031 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 2032 if (RT_SUCCESS(rc)) 2033 cb += cbFile; 2034 } 2035 } 2036 2037 LogFlowFunc(("returns %lld\n", cb)); 2038 return cb; 2039 } 2040 2041 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 2042 static int qcowGetPCHSGeometry(void *pBackendData, 2043 PVDGEOMETRY pPCHSGeometry) 2044 { 2045 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 2046 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2047 int rc; 2048 2049 AssertPtr(pImage); 2050 2051 if (pImage) 2052 { 2053 if (pImage->PCHSGeometry.cCylinders) 2054 { 2055 *pPCHSGeometry = pImage->PCHSGeometry; 2056 rc = VINF_SUCCESS; 2057 } 2058 else 2059 rc = VERR_VD_GEOMETRY_NOT_SET; 2060 } 2061 else 2062 rc = VERR_VD_NOT_OPENED; 2063 2064 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2065 return rc; 2066 } 2067 2068 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 2069 static int qcowSetPCHSGeometry(void *pBackendData, 2070 PCVDGEOMETRY pPCHSGeometry) 2071 { 2072 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2073 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2074 int rc; 2075 2076 AssertPtr(pImage); 2077 2078 if (pImage) 2079 { 2080 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2081 { 2082 rc = VERR_VD_IMAGE_READ_ONLY; 2083 goto out; 2084 } 2085 2086 pImage->PCHSGeometry = *pPCHSGeometry; 2087 rc = VINF_SUCCESS; 2088 } 2089 else 2090 rc = VERR_VD_NOT_OPENED; 2091 2092 out: 2093 LogFlowFunc(("returns %Rrc\n", rc)); 2094 return rc; 2095 } 2096 2097 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 2098 static int qcowGetLCHSGeometry(void *pBackendData, 2099 PVDGEOMETRY pLCHSGeometry) 2100 { 2101 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 2102 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2103 int rc; 2104 2105 AssertPtr(pImage); 2106 2107 if (pImage) 2108 { 2109 if (pImage->LCHSGeometry.cCylinders) 2110 { 2111 *pLCHSGeometry = pImage->LCHSGeometry; 2112 rc = VINF_SUCCESS; 2113 } 2114 else 2115 rc = VERR_VD_GEOMETRY_NOT_SET; 2116 } 2117 else 2118 rc = VERR_VD_NOT_OPENED; 2119 2120 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2121 return rc; 2122 } 2123 2124 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 2125 static int qcowSetLCHSGeometry(void *pBackendData, 2126 PCVDGEOMETRY pLCHSGeometry) 2127 { 2128 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2129 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2130 int rc; 2131 2132 AssertPtr(pImage); 2133 2134 if (pImage) 2135 { 2136 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2137 { 2138 rc = VERR_VD_IMAGE_READ_ONLY; 2139 goto out; 2140 } 2141 2142 pImage->LCHSGeometry = *pLCHSGeometry; 2143 rc = VINF_SUCCESS; 2144 } 2145 else 2146 rc = VERR_VD_NOT_OPENED; 2147 2148 out: 2149 LogFlowFunc(("returns %Rrc\n", rc)); 2150 return rc; 2151 } 2152 2153 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 2154 static unsigned qcowGetImageFlags(void *pBackendData) 2155 { 2156 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2157 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2158 unsigned uImageFlags; 2159 2160 AssertPtr(pImage); 2161 2162 if (pImage) 2163 uImageFlags = pImage->uImageFlags; 2164 else 2165 uImageFlags = 0; 2166 2167 LogFlowFunc(("returns %#x\n", uImageFlags)); 2168 return uImageFlags; 2169 } 2170 2171 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 2172 static unsigned qcowGetOpenFlags(void *pBackendData) 2173 { 2174 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2175 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2176 unsigned uOpenFlags; 2177 2178 AssertPtr(pImage); 2179 2180 if (pImage) 2181 uOpenFlags = pImage->uOpenFlags; 2182 else 2183 uOpenFlags = 0; 2184 2185 LogFlowFunc(("returns %#x\n", uOpenFlags)); 2186 return uOpenFlags; 2187 } 2188 2189 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 2190 static int qcowSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 2191 { 2192 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2193 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2194 int rc; 2195 2196 /* Image must be opened and the new flags must be valid. */ 2197 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 2198 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 2199 { 2200 rc = VERR_INVALID_PARAMETER; 2201 goto out; 2202 } 2203 2204 /* Implement this operation via reopening the image. */ 2205 rc = qcowFreeImage(pImage, false); 2206 if (RT_FAILURE(rc)) 2207 goto out; 2208 rc = qcowOpenImage(pImage, uOpenFlags); 2209 2210 out: 2211 LogFlowFunc(("returns %Rrc\n", rc)); 2212 return rc; 2213 } 2214 2215 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 2216 static int qcowGetComment(void *pBackendData, char *pszComment, 2217 size_t cbComment) 2218 { 2219 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2220 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2221 int rc; 2222 2223 AssertPtr(pImage); 2224 2225 if (pImage) 2226 rc = VERR_NOT_SUPPORTED; 2227 else 2228 rc = VERR_VD_NOT_OPENED; 2229 2230 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 2231 return rc; 2232 } 2233 2234 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 2235 static int qcowSetComment(void *pBackendData, const char *pszComment) 2236 { 2237 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2238 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2239 int rc; 2240 2241 AssertPtr(pImage); 2242 2243 if (pImage) 2244 { 2245 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2246 rc = VERR_VD_IMAGE_READ_ONLY; 2247 else 2248 rc = VERR_NOT_SUPPORTED; 2249 } 2250 else 2251 rc = VERR_VD_NOT_OPENED; 2252 2253 LogFlowFunc(("returns %Rrc\n", rc)); 2254 return rc; 2255 } 2256 2257 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 2258 static int qcowGetUuid(void *pBackendData, PRTUUID pUuid) 2259 { 2260 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2261 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2262 int rc; 2263 2264 AssertPtr(pImage); 2265 2266 if (pImage) 2267 rc = VERR_NOT_SUPPORTED; 2268 else 2269 rc = VERR_VD_NOT_OPENED; 2270 2271 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2272 return rc; 2273 } 2274 2275 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 2276 static int qcowSetUuid(void *pBackendData, PCRTUUID pUuid) 2277 { 2278 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2279 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2280 int rc; 2281 2282 LogFlowFunc(("%RTuuid\n", pUuid)); 2283 AssertPtr(pImage); 2284 2285 if (pImage) 2286 { 2287 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2288 rc = VERR_NOT_SUPPORTED; 2289 else 2290 rc = VERR_VD_IMAGE_READ_ONLY; 2291 } 2292 else 2293 rc = VERR_VD_NOT_OPENED; 2294 2295 LogFlowFunc(("returns %Rrc\n", rc)); 2296 return rc; 2297 } 2298 2299 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 2300 static int qcowGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2301 { 2302 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2303 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2304 int rc; 2305 2306 AssertPtr(pImage); 2307 2308 if (pImage) 2309 rc = VERR_NOT_SUPPORTED; 2310 else 2311 rc = VERR_VD_NOT_OPENED; 2312 2313 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2314 return rc; 2315 } 2316 2317 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 2318 static int qcowSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2319 { 2320 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2321 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2322 int rc; 2323 2324 AssertPtr(pImage); 2325 2326 if (pImage) 2327 { 2328 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2329 rc = VERR_NOT_SUPPORTED; 2330 else 2331 rc = VERR_VD_IMAGE_READ_ONLY; 2332 } 2333 else 2334 rc = VERR_VD_NOT_OPENED; 2335 2336 LogFlowFunc(("returns %Rrc\n", rc)); 2337 return rc; 2338 } 2339 2340 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 2341 static int qcowGetParentUuid(void *pBackendData, PRTUUID pUuid) 2342 { 2343 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2344 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2345 int rc; 2346 2347 AssertPtr(pImage); 2348 2349 if (pImage) 2350 rc = VERR_NOT_SUPPORTED; 2351 else 2352 rc = VERR_VD_NOT_OPENED; 2353 2354 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2355 return rc; 2356 } 2357 2358 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 2359 static int qcowSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2360 { 2361 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2362 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2363 int rc; 2364 2365 AssertPtr(pImage); 2366 2367 if (pImage) 2368 { 2369 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2370 rc = VERR_NOT_SUPPORTED; 2371 else 2372 rc = VERR_VD_IMAGE_READ_ONLY; 2373 } 2374 else 2375 rc = VERR_VD_NOT_OPENED; 2376 2377 LogFlowFunc(("returns %Rrc\n", rc)); 2378 return rc; 2379 } 2380 2381 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 2382 static int qcowGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2383 { 2384 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2385 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2386 int rc; 2387 2388 AssertPtr(pImage); 2389 2390 if (pImage) 2391 rc = VERR_NOT_SUPPORTED; 2392 else 2393 rc = VERR_VD_NOT_OPENED; 2394 2395 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2396 return rc; 2397 } 2398 2399 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 2400 static int qcowSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2401 { 2402 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2403 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2404 int rc; 2405 2406 AssertPtr(pImage); 2407 2408 if (pImage) 2409 { 2410 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2411 rc = VERR_NOT_SUPPORTED; 2412 else 2413 rc = VERR_VD_IMAGE_READ_ONLY; 2414 } 2415 else 2416 rc = VERR_VD_NOT_OPENED; 2417 2418 LogFlowFunc(("returns %Rrc\n", rc)); 2419 return rc; 2420 } 2421 2422 /** @copydoc VBOXHDDBACKEND::pfnDump */ 2423 static void qcowDump(void *pBackendData) 2424 { 2425 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2426 2427 AssertPtr(pImage); 2428 if (pImage) 2429 { 2430 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cSector=%llu\n", 2431 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2432 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2433 pImage->cbSize / 512); 2434 } 2435 } 2436 2437 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */ 2438 static int qcowGetParentFilename(void *pBackendData, char **ppszParentFilename) 2439 { 2440 int rc = VINF_SUCCESS; 2441 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2442 2443 AssertPtr(pImage); 2444 if (pImage) 2445 if (pImage->pszFilename) 2446 *ppszParentFilename = RTStrDup(pImage->pszBackingFilename); 2447 else 2448 rc = VERR_NOT_SUPPORTED; 2449 else 2450 rc = VERR_VD_NOT_OPENED; 2451 2452 LogFlowFunc(("returns %Rrc\n", rc)); 2453 return rc; 2454 } 2455 2456 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */ 2457 static int qcowSetParentFilename(void *pBackendData, const char *pszParentFilename) 2458 { 2459 int rc = VINF_SUCCESS; 2460 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2461 2462 AssertPtr(pImage); 2463 if (pImage) 2464 { 2465 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2466 rc = VERR_VD_IMAGE_READ_ONLY; 2467 else if ( pImage->pszBackingFilename 2468 && (strlen(pszParentFilename) > pImage->cbBackingFilename)) 2469 rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */ 2470 else 2471 { 2472 if (pImage->pszBackingFilename) 2473 RTStrFree(pImage->pszBackingFilename); 2474 pImage->pszBackingFilename = RTStrDup(pszParentFilename); 2475 if (!pImage->pszBackingFilename) 2476 rc = VERR_NO_MEMORY; 2477 else 2478 { 2479 if (!pImage->offBackingFilename) 2480 { 2481 /* Allocate new cluster. */ 2482 uint64_t offData = qcowClusterAllocate(pImage, 1); 2483 2484 Assert((offData & UINT32_MAX) == offData); 2485 pImage->offBackingFilename = (uint32_t)offData; 2486 pImage->cbBackingFilename = strlen(pszParentFilename); 2487 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, 2488 offData + pImage->cbCluster); 2489 } 2490 2491 if (RT_SUCCESS(rc)) 2492 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2493 pImage->offBackingFilename, 2494 pImage->pszBackingFilename, 2495 strlen(pImage->pszBackingFilename)); 2496 } 2497 } 2498 } 2499 else 2500 rc = VERR_VD_NOT_OPENED; 2501 2502 LogFlowFunc(("returns %Rrc\n", rc)); 2503 return rc; 2504 } 2505 2506 static int qcowAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 2507 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 2508 { 2509 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 2510 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 2511 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2512 uint32_t offCluster = 0; 2513 uint32_t idxL1 = 0; 2514 uint32_t idxL2 = 0; 2515 uint64_t offFile = 0; 2516 int rc; 2517 2518 AssertPtr(pImage); 2519 Assert(uOffset % 512 == 0); 2520 Assert(cbToRead % 512 == 0); 2521 2522 if (!VALID_PTR(pIoCtx) || !cbToRead) 2523 { 2524 rc = VERR_INVALID_PARAMETER; 2525 goto out; 2526 } 2527 2528 if ( uOffset + cbToRead > pImage->cbSize 2529 || cbToRead == 0) 2530 { 2531 rc = VERR_INVALID_PARAMETER; 2532 goto out; 2533 } 2534 2535 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 2536 2537 /* Clip read size to remain in the cluster. */ 2538 cbToRead = RT_MIN(cbToRead, pImage->cbCluster - offCluster); 2539 2540 /* Get offset in image. */ 2541 rc = qcowConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster, 2542 &offFile); 1707 rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offFile); 2543 1708 if (RT_SUCCESS(rc)) 2544 1709 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile, … … 2556 1721 } 2557 1722 2558 static int qcowAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 2559 PVDIOCTX pIoCtx, 2560 size_t *pcbWriteProcess, size_t *pcbPreRead, 2561 size_t *pcbPostRead, unsigned fWrite) 1723 static int qcowWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 1724 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 1725 size_t *pcbPostRead, unsigned fWrite) 2562 1726 { 2563 1727 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", … … 2601 1765 2602 1766 /* Get offset in image. */ 2603 rc = qcowConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster, 2604 &offImage); 1767 rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage); 2605 1768 if (RT_SUCCESS(rc)) 2606 1769 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, … … 2676 1839 else 2677 1840 { 2678 rc = qcowL2TblCacheFetchAsync(pImage, pIoCtx, pImage->paL1Table[idxL1], 2679 &pL2Entry); 2680 1841 rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1], 1842 &pL2Entry); 2681 1843 if (RT_SUCCESS(rc)) 2682 1844 { … … 2741 1903 } 2742 1904 2743 static int qcow AsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)1905 static int qcowFlush(void *pBackendData, PVDIOCTX pIoCtx) 2744 1906 { 2745 1907 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); … … 2757 1919 return rc; 2758 1920 } 1921 1922 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 1923 static unsigned qcowGetVersion(void *pBackendData) 1924 { 1925 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1926 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1927 1928 AssertPtr(pImage); 1929 1930 if (pImage) 1931 return pImage->uVersion; 1932 else 1933 return 0; 1934 } 1935 1936 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 1937 static uint64_t qcowGetSize(void *pBackendData) 1938 { 1939 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1940 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1941 uint64_t cb = 0; 1942 1943 AssertPtr(pImage); 1944 1945 if (pImage && pImage->pStorage) 1946 cb = pImage->cbSize; 1947 1948 LogFlowFunc(("returns %llu\n", cb)); 1949 return cb; 1950 } 1951 1952 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 1953 static uint64_t qcowGetFileSize(void *pBackendData) 1954 { 1955 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1956 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1957 uint64_t cb = 0; 1958 1959 AssertPtr(pImage); 1960 1961 if (pImage) 1962 { 1963 uint64_t cbFile; 1964 if (pImage->pStorage) 1965 { 1966 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 1967 if (RT_SUCCESS(rc)) 1968 cb += cbFile; 1969 } 1970 } 1971 1972 LogFlowFunc(("returns %lld\n", cb)); 1973 return cb; 1974 } 1975 1976 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 1977 static int qcowGetPCHSGeometry(void *pBackendData, 1978 PVDGEOMETRY pPCHSGeometry) 1979 { 1980 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 1981 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1982 int rc; 1983 1984 AssertPtr(pImage); 1985 1986 if (pImage) 1987 { 1988 if (pImage->PCHSGeometry.cCylinders) 1989 { 1990 *pPCHSGeometry = pImage->PCHSGeometry; 1991 rc = VINF_SUCCESS; 1992 } 1993 else 1994 rc = VERR_VD_GEOMETRY_NOT_SET; 1995 } 1996 else 1997 rc = VERR_VD_NOT_OPENED; 1998 1999 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2000 return rc; 2001 } 2002 2003 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 2004 static int qcowSetPCHSGeometry(void *pBackendData, 2005 PCVDGEOMETRY pPCHSGeometry) 2006 { 2007 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2008 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2009 int rc; 2010 2011 AssertPtr(pImage); 2012 2013 if (pImage) 2014 { 2015 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2016 { 2017 rc = VERR_VD_IMAGE_READ_ONLY; 2018 goto out; 2019 } 2020 2021 pImage->PCHSGeometry = *pPCHSGeometry; 2022 rc = VINF_SUCCESS; 2023 } 2024 else 2025 rc = VERR_VD_NOT_OPENED; 2026 2027 out: 2028 LogFlowFunc(("returns %Rrc\n", rc)); 2029 return rc; 2030 } 2031 2032 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 2033 static int qcowGetLCHSGeometry(void *pBackendData, 2034 PVDGEOMETRY pLCHSGeometry) 2035 { 2036 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 2037 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2038 int rc; 2039 2040 AssertPtr(pImage); 2041 2042 if (pImage) 2043 { 2044 if (pImage->LCHSGeometry.cCylinders) 2045 { 2046 *pLCHSGeometry = pImage->LCHSGeometry; 2047 rc = VINF_SUCCESS; 2048 } 2049 else 2050 rc = VERR_VD_GEOMETRY_NOT_SET; 2051 } 2052 else 2053 rc = VERR_VD_NOT_OPENED; 2054 2055 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2056 return rc; 2057 } 2058 2059 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 2060 static int qcowSetLCHSGeometry(void *pBackendData, 2061 PCVDGEOMETRY pLCHSGeometry) 2062 { 2063 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2064 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2065 int rc; 2066 2067 AssertPtr(pImage); 2068 2069 if (pImage) 2070 { 2071 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2072 { 2073 rc = VERR_VD_IMAGE_READ_ONLY; 2074 goto out; 2075 } 2076 2077 pImage->LCHSGeometry = *pLCHSGeometry; 2078 rc = VINF_SUCCESS; 2079 } 2080 else 2081 rc = VERR_VD_NOT_OPENED; 2082 2083 out: 2084 LogFlowFunc(("returns %Rrc\n", rc)); 2085 return rc; 2086 } 2087 2088 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 2089 static unsigned qcowGetImageFlags(void *pBackendData) 2090 { 2091 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2092 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2093 unsigned uImageFlags; 2094 2095 AssertPtr(pImage); 2096 2097 if (pImage) 2098 uImageFlags = pImage->uImageFlags; 2099 else 2100 uImageFlags = 0; 2101 2102 LogFlowFunc(("returns %#x\n", uImageFlags)); 2103 return uImageFlags; 2104 } 2105 2106 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 2107 static unsigned qcowGetOpenFlags(void *pBackendData) 2108 { 2109 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2110 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2111 unsigned uOpenFlags; 2112 2113 AssertPtr(pImage); 2114 2115 if (pImage) 2116 uOpenFlags = pImage->uOpenFlags; 2117 else 2118 uOpenFlags = 0; 2119 2120 LogFlowFunc(("returns %#x\n", uOpenFlags)); 2121 return uOpenFlags; 2122 } 2123 2124 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 2125 static int qcowSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 2126 { 2127 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2128 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2129 int rc; 2130 2131 /* Image must be opened and the new flags must be valid. */ 2132 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 2133 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 2134 { 2135 rc = VERR_INVALID_PARAMETER; 2136 goto out; 2137 } 2138 2139 /* Implement this operation via reopening the image. */ 2140 rc = qcowFreeImage(pImage, false); 2141 if (RT_FAILURE(rc)) 2142 goto out; 2143 rc = qcowOpenImage(pImage, uOpenFlags); 2144 2145 out: 2146 LogFlowFunc(("returns %Rrc\n", rc)); 2147 return rc; 2148 } 2149 2150 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 2151 static int qcowGetComment(void *pBackendData, char *pszComment, 2152 size_t cbComment) 2153 { 2154 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2155 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2156 int rc; 2157 2158 AssertPtr(pImage); 2159 2160 if (pImage) 2161 rc = VERR_NOT_SUPPORTED; 2162 else 2163 rc = VERR_VD_NOT_OPENED; 2164 2165 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 2166 return rc; 2167 } 2168 2169 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 2170 static int qcowSetComment(void *pBackendData, const char *pszComment) 2171 { 2172 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2173 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2174 int rc; 2175 2176 AssertPtr(pImage); 2177 2178 if (pImage) 2179 { 2180 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2181 rc = VERR_VD_IMAGE_READ_ONLY; 2182 else 2183 rc = VERR_NOT_SUPPORTED; 2184 } 2185 else 2186 rc = VERR_VD_NOT_OPENED; 2187 2188 LogFlowFunc(("returns %Rrc\n", rc)); 2189 return rc; 2190 } 2191 2192 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 2193 static int qcowGetUuid(void *pBackendData, PRTUUID pUuid) 2194 { 2195 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2196 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2197 int rc; 2198 2199 AssertPtr(pImage); 2200 2201 if (pImage) 2202 rc = VERR_NOT_SUPPORTED; 2203 else 2204 rc = VERR_VD_NOT_OPENED; 2205 2206 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2207 return rc; 2208 } 2209 2210 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 2211 static int qcowSetUuid(void *pBackendData, PCRTUUID pUuid) 2212 { 2213 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2214 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2215 int rc; 2216 2217 LogFlowFunc(("%RTuuid\n", pUuid)); 2218 AssertPtr(pImage); 2219 2220 if (pImage) 2221 { 2222 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2223 rc = VERR_NOT_SUPPORTED; 2224 else 2225 rc = VERR_VD_IMAGE_READ_ONLY; 2226 } 2227 else 2228 rc = VERR_VD_NOT_OPENED; 2229 2230 LogFlowFunc(("returns %Rrc\n", rc)); 2231 return rc; 2232 } 2233 2234 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 2235 static int qcowGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2236 { 2237 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2238 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2239 int rc; 2240 2241 AssertPtr(pImage); 2242 2243 if (pImage) 2244 rc = VERR_NOT_SUPPORTED; 2245 else 2246 rc = VERR_VD_NOT_OPENED; 2247 2248 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2249 return rc; 2250 } 2251 2252 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 2253 static int qcowSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2254 { 2255 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2256 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2257 int rc; 2258 2259 AssertPtr(pImage); 2260 2261 if (pImage) 2262 { 2263 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2264 rc = VERR_NOT_SUPPORTED; 2265 else 2266 rc = VERR_VD_IMAGE_READ_ONLY; 2267 } 2268 else 2269 rc = VERR_VD_NOT_OPENED; 2270 2271 LogFlowFunc(("returns %Rrc\n", rc)); 2272 return rc; 2273 } 2274 2275 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 2276 static int qcowGetParentUuid(void *pBackendData, PRTUUID pUuid) 2277 { 2278 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2279 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2280 int rc; 2281 2282 AssertPtr(pImage); 2283 2284 if (pImage) 2285 rc = VERR_NOT_SUPPORTED; 2286 else 2287 rc = VERR_VD_NOT_OPENED; 2288 2289 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2290 return rc; 2291 } 2292 2293 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 2294 static int qcowSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2295 { 2296 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2297 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2298 int rc; 2299 2300 AssertPtr(pImage); 2301 2302 if (pImage) 2303 { 2304 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2305 rc = VERR_NOT_SUPPORTED; 2306 else 2307 rc = VERR_VD_IMAGE_READ_ONLY; 2308 } 2309 else 2310 rc = VERR_VD_NOT_OPENED; 2311 2312 LogFlowFunc(("returns %Rrc\n", rc)); 2313 return rc; 2314 } 2315 2316 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 2317 static int qcowGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2318 { 2319 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2320 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2321 int rc; 2322 2323 AssertPtr(pImage); 2324 2325 if (pImage) 2326 rc = VERR_NOT_SUPPORTED; 2327 else 2328 rc = VERR_VD_NOT_OPENED; 2329 2330 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2331 return rc; 2332 } 2333 2334 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 2335 static int qcowSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2336 { 2337 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2338 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2339 int rc; 2340 2341 AssertPtr(pImage); 2342 2343 if (pImage) 2344 { 2345 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2346 rc = VERR_NOT_SUPPORTED; 2347 else 2348 rc = VERR_VD_IMAGE_READ_ONLY; 2349 } 2350 else 2351 rc = VERR_VD_NOT_OPENED; 2352 2353 LogFlowFunc(("returns %Rrc\n", rc)); 2354 return rc; 2355 } 2356 2357 /** @copydoc VBOXHDDBACKEND::pfnDump */ 2358 static void qcowDump(void *pBackendData) 2359 { 2360 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2361 2362 AssertPtr(pImage); 2363 if (pImage) 2364 { 2365 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cSector=%llu\n", 2366 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2367 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2368 pImage->cbSize / 512); 2369 } 2370 } 2371 2372 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */ 2373 static int qcowGetParentFilename(void *pBackendData, char **ppszParentFilename) 2374 { 2375 int rc = VINF_SUCCESS; 2376 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2377 2378 AssertPtr(pImage); 2379 if (pImage) 2380 if (pImage->pszFilename) 2381 *ppszParentFilename = RTStrDup(pImage->pszBackingFilename); 2382 else 2383 rc = VERR_NOT_SUPPORTED; 2384 else 2385 rc = VERR_VD_NOT_OPENED; 2386 2387 LogFlowFunc(("returns %Rrc\n", rc)); 2388 return rc; 2389 } 2390 2391 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */ 2392 static int qcowSetParentFilename(void *pBackendData, const char *pszParentFilename) 2393 { 2394 int rc = VINF_SUCCESS; 2395 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2396 2397 AssertPtr(pImage); 2398 if (pImage) 2399 { 2400 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2401 rc = VERR_VD_IMAGE_READ_ONLY; 2402 else if ( pImage->pszBackingFilename 2403 && (strlen(pszParentFilename) > pImage->cbBackingFilename)) 2404 rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */ 2405 else 2406 { 2407 if (pImage->pszBackingFilename) 2408 RTStrFree(pImage->pszBackingFilename); 2409 pImage->pszBackingFilename = RTStrDup(pszParentFilename); 2410 if (!pImage->pszBackingFilename) 2411 rc = VERR_NO_MEMORY; 2412 else 2413 { 2414 if (!pImage->offBackingFilename) 2415 { 2416 /* Allocate new cluster. */ 2417 uint64_t offData = qcowClusterAllocate(pImage, 1); 2418 2419 Assert((offData & UINT32_MAX) == offData); 2420 pImage->offBackingFilename = (uint32_t)offData; 2421 pImage->cbBackingFilename = strlen(pszParentFilename); 2422 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, 2423 offData + pImage->cbCluster); 2424 } 2425 2426 if (RT_SUCCESS(rc)) 2427 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2428 pImage->offBackingFilename, 2429 pImage->pszBackingFilename, 2430 strlen(pImage->pszBackingFilename)); 2431 } 2432 } 2433 } 2434 else 2435 rc = VERR_VD_NOT_OPENED; 2436 2437 LogFlowFunc(("returns %Rrc\n", rc)); 2438 return rc; 2439 } 2440 2441 2759 2442 2760 2443 VBOXHDDBACKEND g_QCowBackend = … … 2788 2471 /* pfnFlush */ 2789 2472 qcowFlush, 2473 /* pfnDiscard */ 2474 NULL, 2790 2475 /* pfnGetVersion */ 2791 2476 qcowGetVersion, … … 2840 2525 /* pfnSetParentFilename */ 2841 2526 qcowSetParentFilename, 2842 /* pfnAsyncRead */2843 qcowAsyncRead,2844 /* pfnAsyncWrite */2845 qcowAsyncWrite,2846 /* pfnAsyncFlush */2847 qcowAsyncFlush,2848 2527 /* pfnComposeLocation */ 2849 2528 genericFileComposeLocation, … … 2854 2533 /* pfnResize */ 2855 2534 NULL, 2856 /* pfnDiscard */2857 NULL,2858 /* pfnAsyncDiscard */2859 NULL,2860 2535 /* pfnRepair */ 2861 2536 NULL -
trunk/src/VBox/Storage/QED.cpp
r44233 r44252 772 772 * VERR_VD_BLOCK_FREE if the cluster is not yet allocated. 773 773 * @param pImage The image instance data. 774 * @param idxL1 The L1 index.775 * @param idxL2 The L2 index.776 * @param offCluster Offset inside the cluster.777 * @param poffImage Where to store the image offset on success;778 */779 static int qedConvertToImageOffset(PQEDIMAGE pImage, uint32_t idxL1, uint32_t idxL2,780 uint32_t offCluster, uint64_t *poffImage)781 {782 int rc = VERR_VD_BLOCK_FREE;783 LogFlowFunc(("pImage=%#p idxL1=%u idxL2=%u offCluster=%u poffImage=%#p\n",784 pImage, idxL1, idxL2, offCluster, poffImage));785 786 AssertReturn(idxL1 < pImage->cTableEntries, VERR_INVALID_PARAMETER);787 AssertReturn(idxL2 < pImage->cTableEntries, VERR_INVALID_PARAMETER);788 789 if (pImage->paL1Table[idxL1])790 {791 PQEDL2CACHEENTRY pL2Entry;792 793 rc = qedL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);794 if (RT_SUCCESS(rc))795 {796 LogFlowFunc(("cluster start offset %llu\n", pL2Entry->paL2Tbl[idxL2]));797 /* Get real file offset. */798 if (pL2Entry->paL2Tbl[idxL2])799 *poffImage = pL2Entry->paL2Tbl[idxL2] + offCluster;800 else801 rc = VERR_VD_BLOCK_FREE;802 803 qedL2TblCacheEntryRelease(pL2Entry);804 }805 }806 807 LogFlowFunc(("returns rc=%Rrc\n", rc));808 return rc;809 }810 811 /**812 * Returns the real image offset for a given cluster or an error if the cluster is not813 * yet allocated- version for async I/O.814 *815 * @returns VBox status code.816 * VERR_VD_BLOCK_FREE if the cluster is not yet allocated.817 * @param pImage The image instance data.818 774 * @param pIoCtx The I/O context. 819 775 * @param idxL1 The L1 index. … … 822 778 * @param poffImage Where to store the image offset on success; 823 779 */ 824 static int qedConvertToImageOffset Async(PQEDIMAGE pImage, PVDIOCTX pIoCtx,825 826 780 static int qedConvertToImageOffset(PQEDIMAGE pImage, PVDIOCTX pIoCtx, 781 uint32_t idxL1, uint32_t idxL2, 782 uint32_t offCluster, uint64_t *poffImage) 827 783 { 828 784 int rc = VERR_VD_BLOCK_FREE; … … 1801 1757 } 1802 1758 1803 /** @copydoc VBOXHDDBACKEND::pfnRead */ 1804 static int qedRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 1805 size_t cbToRead, size_t *pcbActuallyRead) 1806 { 1807 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1808 pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 1759 static int qedRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 1760 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1761 { 1762 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1763 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 1809 1764 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 1810 1765 uint32_t offCluster = 0; … … 1818 1773 Assert(cbToRead % 512 == 0); 1819 1774 1775 if (!VALID_PTR(pIoCtx) || !cbToRead) 1776 { 1777 rc = VERR_INVALID_PARAMETER; 1778 goto out; 1779 } 1780 1820 1781 if ( uOffset + cbToRead > pImage->cbSize 1821 1782 || cbToRead == 0) … … 1826 1787 1827 1788 qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 1828 LogFlowFunc(("idxL1=%u idxL2=%u offCluster=%u\n", idxL1, idxL2, offCluster));1829 1789 1830 1790 /* Clip read size to remain in the cluster. */ … … 1832 1792 1833 1793 /* Get offset in image. */ 1834 rc = qedConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offFile); 1835 if (RT_SUCCESS(rc)) 1836 { 1837 LogFlowFunc(("offFile=%llu\n", offFile)); 1838 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offFile, 1839 pvBuf, cbToRead); 1840 } 1841 1842 if ( (RT_SUCCESS(rc) || rc == VERR_VD_BLOCK_FREE) 1843 && pcbActuallyRead) 1844 *pcbActuallyRead = cbToRead; 1845 1846 out: 1847 LogFlowFunc(("returns %Rrc\n", rc)); 1848 return rc; 1849 } 1850 1851 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1852 static int qedWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 1853 size_t cbToWrite, size_t *pcbWriteProcess, 1854 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 1855 { 1856 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 1857 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 1858 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 1859 uint32_t offCluster = 0; 1860 uint32_t idxL1 = 0; 1861 uint32_t idxL2 = 0; 1862 uint64_t offImage = 0; 1863 int rc; 1864 1865 AssertPtr(pImage); 1866 Assert(uOffset % 512 == 0); 1867 Assert(cbToWrite % 512 == 0); 1868 1869 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1870 { 1871 rc = VERR_VD_IMAGE_READ_ONLY; 1872 goto out; 1873 } 1874 1875 if ( uOffset + cbToWrite > pImage->cbSize 1876 || cbToWrite == 0) 1877 { 1878 rc = VERR_INVALID_PARAMETER; 1879 goto out; 1880 } 1881 1882 /* Convert offset to L1, L2 index and cluster offset. */ 1883 qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 1884 1885 /* Clip write size to remain in the cluster. */ 1886 cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster); 1887 Assert(!(cbToWrite % 512)); 1888 1889 /* Get offset in image. */ 1890 rc = qedConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offImage); 1891 if (RT_SUCCESS(rc)) 1892 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offImage, 1893 pvBuf, cbToWrite); 1894 else if (rc == VERR_VD_BLOCK_FREE) 1895 { 1896 if ( cbToWrite == pImage->cbCluster 1897 && !(fWrite & VD_WRITE_NO_ALLOC)) 1898 { 1899 PQEDL2CACHEENTRY pL2Entry = NULL; 1900 1901 /* Full cluster write to previously unallocated cluster. 1902 * Allocate cluster and write data. */ 1903 Assert(!offCluster); 1904 1905 do 1906 { 1907 uint64_t idxUpdateLe = 0; 1908 1909 /* Check if we have to allocate a new cluster for L2 tables. */ 1910 if (!pImage->paL1Table[idxL1]) 1911 { 1912 uint64_t offL2Tbl = qedClusterAllocate(pImage, qedByte2Cluster(pImage, pImage->cbTable)); 1913 1914 pL2Entry = qedL2TblCacheEntryAlloc(pImage); 1915 if (!pL2Entry) 1916 { 1917 rc = VERR_NO_MEMORY; 1918 break; 1919 } 1920 1921 pL2Entry->offL2Tbl = offL2Tbl; 1922 memset(pL2Entry->paL2Tbl, 0, pImage->cbTable); 1923 qedL2TblCacheEntryInsert(pImage, pL2Entry); 1924 1925 /* 1926 * Write the L2 table first and link to the L1 table afterwards. 1927 * If something unexpected happens the worst case which can happen 1928 * is a leak of some clusters. 1929 */ 1930 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offL2Tbl, 1931 pL2Entry->paL2Tbl, pImage->cbTable); 1932 if (RT_FAILURE(rc)) 1933 break; 1934 1935 /* Write the L1 link now. */ 1936 pImage->paL1Table[idxL1] = offL2Tbl; 1937 idxUpdateLe = RT_H2LE_U64(offL2Tbl); 1938 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1939 pImage->offL1Table + idxL1*sizeof(uint64_t), 1940 &idxUpdateLe, sizeof(uint64_t)); 1941 if (RT_FAILURE(rc)) 1942 break; 1943 } 1944 else 1945 rc = qedL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry); 1946 1947 if (RT_SUCCESS(rc)) 1948 { 1949 /* Allocate new cluster for the data. */ 1950 uint64_t offData = qedClusterAllocate(pImage, 1); 1951 1952 /* Write data. */ 1953 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1954 offData, pvBuf, cbToWrite); 1955 if (RT_FAILURE(rc)) 1956 break; 1957 1958 /* Link L2 table and update it. */ 1959 pL2Entry->paL2Tbl[idxL2] = offData; 1960 idxUpdateLe = RT_H2LE_U64(offData); 1961 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1962 pImage->paL1Table[idxL1] + idxL2*sizeof(uint64_t), 1963 &idxUpdateLe, sizeof(uint64_t)); 1964 qedL2TblCacheEntryRelease(pL2Entry); 1965 } 1966 1967 } while (0); 1968 1969 *pcbPreRead = 0; 1970 *pcbPostRead = 0; 1971 } 1972 else 1973 { 1974 /* Trying to do a partial write to an unallocated cluster. Don't do 1975 * anything except letting the upper layer know what to do. */ 1976 *pcbPreRead = offCluster; 1977 *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead; 1978 } 1979 } 1980 1981 if (pcbWriteProcess) 1982 *pcbWriteProcess = cbToWrite; 1983 1984 out: 1985 LogFlowFunc(("returns %Rrc\n", rc)); 1986 return rc; 1987 } 1988 1989 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1990 static int qedFlush(void *pBackendData) 1991 { 1992 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1993 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 1994 int rc; 1995 1996 rc = qedFlushImage(pImage); 1997 LogFlowFunc(("returns %Rrc\n", rc)); 1998 return rc; 1999 } 2000 2001 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 2002 static unsigned qedGetVersion(void *pBackendData) 2003 { 2004 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2005 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2006 2007 AssertPtr(pImage); 2008 2009 if (pImage) 2010 return 1; 2011 else 2012 return 0; 2013 } 2014 2015 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 2016 static uint64_t qedGetSize(void *pBackendData) 2017 { 2018 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2019 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2020 uint64_t cb = 0; 2021 2022 AssertPtr(pImage); 2023 2024 if (pImage && pImage->pStorage) 2025 cb = pImage->cbSize; 2026 2027 LogFlowFunc(("returns %llu\n", cb)); 2028 return cb; 2029 } 2030 2031 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 2032 static uint64_t qedGetFileSize(void *pBackendData) 2033 { 2034 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2035 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2036 uint64_t cb = 0; 2037 2038 AssertPtr(pImage); 2039 2040 if (pImage) 2041 { 2042 uint64_t cbFile; 2043 if (pImage->pStorage) 2044 { 2045 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 2046 if (RT_SUCCESS(rc)) 2047 cb += cbFile; 2048 } 2049 } 2050 2051 LogFlowFunc(("returns %lld\n", cb)); 2052 return cb; 2053 } 2054 2055 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 2056 static int qedGetPCHSGeometry(void *pBackendData, 2057 PVDGEOMETRY pPCHSGeometry) 2058 { 2059 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 2060 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2061 int rc; 2062 2063 AssertPtr(pImage); 2064 2065 if (pImage) 2066 { 2067 if (pImage->PCHSGeometry.cCylinders) 2068 { 2069 *pPCHSGeometry = pImage->PCHSGeometry; 2070 rc = VINF_SUCCESS; 2071 } 2072 else 2073 rc = VERR_VD_GEOMETRY_NOT_SET; 2074 } 2075 else 2076 rc = VERR_VD_NOT_OPENED; 2077 2078 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2079 return rc; 2080 } 2081 2082 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 2083 static int qedSetPCHSGeometry(void *pBackendData, 2084 PCVDGEOMETRY pPCHSGeometry) 2085 { 2086 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2087 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2088 int rc; 2089 2090 AssertPtr(pImage); 2091 2092 if (pImage) 2093 { 2094 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2095 { 2096 rc = VERR_VD_IMAGE_READ_ONLY; 2097 goto out; 2098 } 2099 2100 pImage->PCHSGeometry = *pPCHSGeometry; 2101 rc = VINF_SUCCESS; 2102 } 2103 else 2104 rc = VERR_VD_NOT_OPENED; 2105 2106 out: 2107 LogFlowFunc(("returns %Rrc\n", rc)); 2108 return rc; 2109 } 2110 2111 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 2112 static int qedGetLCHSGeometry(void *pBackendData, 2113 PVDGEOMETRY pLCHSGeometry) 2114 { 2115 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 2116 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2117 int rc; 2118 2119 AssertPtr(pImage); 2120 2121 if (pImage) 2122 { 2123 if (pImage->LCHSGeometry.cCylinders) 2124 { 2125 *pLCHSGeometry = pImage->LCHSGeometry; 2126 rc = VINF_SUCCESS; 2127 } 2128 else 2129 rc = VERR_VD_GEOMETRY_NOT_SET; 2130 } 2131 else 2132 rc = VERR_VD_NOT_OPENED; 2133 2134 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2135 return rc; 2136 } 2137 2138 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 2139 static int qedSetLCHSGeometry(void *pBackendData, 2140 PCVDGEOMETRY pLCHSGeometry) 2141 { 2142 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2143 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2144 int rc; 2145 2146 AssertPtr(pImage); 2147 2148 if (pImage) 2149 { 2150 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2151 { 2152 rc = VERR_VD_IMAGE_READ_ONLY; 2153 goto out; 2154 } 2155 2156 pImage->LCHSGeometry = *pLCHSGeometry; 2157 rc = VINF_SUCCESS; 2158 } 2159 else 2160 rc = VERR_VD_NOT_OPENED; 2161 2162 out: 2163 LogFlowFunc(("returns %Rrc\n", rc)); 2164 return rc; 2165 } 2166 2167 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 2168 static unsigned qedGetImageFlags(void *pBackendData) 2169 { 2170 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2171 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2172 unsigned uImageFlags; 2173 2174 AssertPtr(pImage); 2175 2176 if (pImage) 2177 uImageFlags = pImage->uImageFlags; 2178 else 2179 uImageFlags = 0; 2180 2181 LogFlowFunc(("returns %#x\n", uImageFlags)); 2182 return uImageFlags; 2183 } 2184 2185 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 2186 static unsigned qedGetOpenFlags(void *pBackendData) 2187 { 2188 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2189 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2190 unsigned uOpenFlags; 2191 2192 AssertPtr(pImage); 2193 2194 if (pImage) 2195 uOpenFlags = pImage->uOpenFlags; 2196 else 2197 uOpenFlags = 0; 2198 2199 LogFlowFunc(("returns %#x\n", uOpenFlags)); 2200 return uOpenFlags; 2201 } 2202 2203 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 2204 static int qedSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 2205 { 2206 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2207 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2208 int rc; 2209 2210 /* Image must be opened and the new flags must be valid. */ 2211 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 2212 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 2213 { 2214 rc = VERR_INVALID_PARAMETER; 2215 goto out; 2216 } 2217 2218 /* Implement this operation via reopening the image. */ 2219 rc = qedFreeImage(pImage, false); 2220 if (RT_FAILURE(rc)) 2221 goto out; 2222 rc = qedOpenImage(pImage, uOpenFlags); 2223 2224 out: 2225 LogFlowFunc(("returns %Rrc\n", rc)); 2226 return rc; 2227 } 2228 2229 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 2230 static int qedGetComment(void *pBackendData, char *pszComment, 2231 size_t cbComment) 2232 { 2233 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2234 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2235 int rc; 2236 2237 AssertPtr(pImage); 2238 2239 if (pImage) 2240 rc = VERR_NOT_SUPPORTED; 2241 else 2242 rc = VERR_VD_NOT_OPENED; 2243 2244 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 2245 return rc; 2246 } 2247 2248 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 2249 static int qedSetComment(void *pBackendData, const char *pszComment) 2250 { 2251 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2252 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2253 int rc; 2254 2255 AssertPtr(pImage); 2256 2257 if (pImage) 2258 { 2259 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2260 rc = VERR_VD_IMAGE_READ_ONLY; 2261 else 2262 rc = VERR_NOT_SUPPORTED; 2263 } 2264 else 2265 rc = VERR_VD_NOT_OPENED; 2266 2267 LogFlowFunc(("returns %Rrc\n", rc)); 2268 return rc; 2269 } 2270 2271 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 2272 static int qedGetUuid(void *pBackendData, PRTUUID pUuid) 2273 { 2274 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2275 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2276 int rc; 2277 2278 AssertPtr(pImage); 2279 2280 if (pImage) 2281 rc = VERR_NOT_SUPPORTED; 2282 else 2283 rc = VERR_VD_NOT_OPENED; 2284 2285 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2286 return rc; 2287 } 2288 2289 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 2290 static int qedSetUuid(void *pBackendData, PCRTUUID pUuid) 2291 { 2292 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2293 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2294 int rc; 2295 2296 LogFlowFunc(("%RTuuid\n", pUuid)); 2297 AssertPtr(pImage); 2298 2299 if (pImage) 2300 { 2301 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2302 rc = VERR_NOT_SUPPORTED; 2303 else 2304 rc = VERR_VD_IMAGE_READ_ONLY; 2305 } 2306 else 2307 rc = VERR_VD_NOT_OPENED; 2308 2309 LogFlowFunc(("returns %Rrc\n", rc)); 2310 return rc; 2311 } 2312 2313 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 2314 static int qedGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2315 { 2316 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2317 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2318 int rc; 2319 2320 AssertPtr(pImage); 2321 2322 if (pImage) 2323 rc = VERR_NOT_SUPPORTED; 2324 else 2325 rc = VERR_VD_NOT_OPENED; 2326 2327 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2328 return rc; 2329 } 2330 2331 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 2332 static int qedSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2333 { 2334 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2335 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2336 int rc; 2337 2338 AssertPtr(pImage); 2339 2340 if (pImage) 2341 { 2342 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2343 rc = VERR_NOT_SUPPORTED; 2344 else 2345 rc = VERR_VD_IMAGE_READ_ONLY; 2346 } 2347 else 2348 rc = VERR_VD_NOT_OPENED; 2349 2350 LogFlowFunc(("returns %Rrc\n", rc)); 2351 return rc; 2352 } 2353 2354 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 2355 static int qedGetParentUuid(void *pBackendData, PRTUUID pUuid) 2356 { 2357 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2358 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2359 int rc; 2360 2361 AssertPtr(pImage); 2362 2363 if (pImage) 2364 rc = VERR_NOT_SUPPORTED; 2365 else 2366 rc = VERR_VD_NOT_OPENED; 2367 2368 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2369 return rc; 2370 } 2371 2372 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 2373 static int qedSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2374 { 2375 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2376 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2377 int rc; 2378 2379 AssertPtr(pImage); 2380 2381 if (pImage) 2382 { 2383 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2384 rc = VERR_NOT_SUPPORTED; 2385 else 2386 rc = VERR_VD_IMAGE_READ_ONLY; 2387 } 2388 else 2389 rc = VERR_VD_NOT_OPENED; 2390 2391 LogFlowFunc(("returns %Rrc\n", rc)); 2392 return rc; 2393 } 2394 2395 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 2396 static int qedGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2397 { 2398 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2399 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2400 int rc; 2401 2402 AssertPtr(pImage); 2403 2404 if (pImage) 2405 rc = VERR_NOT_SUPPORTED; 2406 else 2407 rc = VERR_VD_NOT_OPENED; 2408 2409 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2410 return rc; 2411 } 2412 2413 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 2414 static int qedSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2415 { 2416 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2417 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2418 int rc; 2419 2420 AssertPtr(pImage); 2421 2422 if (pImage) 2423 { 2424 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2425 rc = VERR_NOT_SUPPORTED; 2426 else 2427 rc = VERR_VD_IMAGE_READ_ONLY; 2428 } 2429 else 2430 rc = VERR_VD_NOT_OPENED; 2431 2432 LogFlowFunc(("returns %Rrc\n", rc)); 2433 return rc; 2434 } 2435 2436 /** @copydoc VBOXHDDBACKEND::pfnDump */ 2437 static void qedDump(void *pBackendData) 2438 { 2439 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2440 2441 AssertPtr(pImage); 2442 if (pImage) 2443 { 2444 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 2445 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2446 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2447 pImage->cbSize / 512); 2448 } 2449 } 2450 2451 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */ 2452 static int qedGetParentFilename(void *pBackendData, char **ppszParentFilename) 2453 { 2454 int rc = VINF_SUCCESS; 2455 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2456 2457 AssertPtr(pImage); 2458 if (pImage) 2459 if (pImage->pszFilename) 2460 *ppszParentFilename = RTStrDup(pImage->pszBackingFilename); 2461 else 2462 rc = VERR_NOT_SUPPORTED; 2463 else 2464 rc = VERR_VD_NOT_OPENED; 2465 2466 LogFlowFunc(("returns %Rrc\n", rc)); 2467 return rc; 2468 } 2469 2470 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */ 2471 static int qedSetParentFilename(void *pBackendData, const char *pszParentFilename) 2472 { 2473 int rc = VINF_SUCCESS; 2474 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2475 2476 AssertPtr(pImage); 2477 if (pImage) 2478 { 2479 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2480 rc = VERR_VD_IMAGE_READ_ONLY; 2481 else if ( pImage->pszBackingFilename 2482 && (strlen(pszParentFilename) > pImage->cbBackingFilename)) 2483 rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */ 2484 else 2485 { 2486 if (pImage->pszBackingFilename) 2487 RTStrFree(pImage->pszBackingFilename); 2488 pImage->pszBackingFilename = RTStrDup(pszParentFilename); 2489 if (!pImage->pszBackingFilename) 2490 rc = VERR_NO_MEMORY; 2491 else 2492 { 2493 if (!pImage->offBackingFilename) 2494 { 2495 /* Allocate new cluster. */ 2496 uint64_t offData = qedClusterAllocate(pImage, 1); 2497 2498 Assert((offData & UINT32_MAX) == offData); 2499 pImage->offBackingFilename = (uint32_t)offData; 2500 pImage->cbBackingFilename = strlen(pszParentFilename); 2501 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, 2502 offData + pImage->cbCluster); 2503 } 2504 2505 if (RT_SUCCESS(rc)) 2506 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2507 pImage->offBackingFilename, 2508 pImage->pszBackingFilename, 2509 strlen(pImage->pszBackingFilename)); 2510 } 2511 } 2512 } 2513 else 2514 rc = VERR_VD_NOT_OPENED; 2515 2516 LogFlowFunc(("returns %Rrc\n", rc)); 2517 return rc; 2518 } 2519 2520 static int qedAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 2521 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 2522 { 2523 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 2524 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 2525 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2526 uint32_t offCluster = 0; 2527 uint32_t idxL1 = 0; 2528 uint32_t idxL2 = 0; 2529 uint64_t offFile = 0; 2530 int rc; 2531 2532 AssertPtr(pImage); 2533 Assert(uOffset % 512 == 0); 2534 Assert(cbToRead % 512 == 0); 2535 2536 if (!VALID_PTR(pIoCtx) || !cbToRead) 2537 { 2538 rc = VERR_INVALID_PARAMETER; 2539 goto out; 2540 } 2541 2542 if ( uOffset + cbToRead > pImage->cbSize 2543 || cbToRead == 0) 2544 { 2545 rc = VERR_INVALID_PARAMETER; 2546 goto out; 2547 } 2548 2549 qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 2550 2551 /* Clip read size to remain in the cluster. */ 2552 cbToRead = RT_MIN(cbToRead, pImage->cbCluster - offCluster); 2553 2554 /* Get offset in image. */ 2555 rc = qedConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster, 2556 &offFile); 1794 rc = qedConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offFile); 2557 1795 if (RT_SUCCESS(rc)) 2558 1796 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile, … … 2570 1808 } 2571 1809 2572 static int qedAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 2573 PVDIOCTX pIoCtx, 2574 size_t *pcbWriteProcess, size_t *pcbPreRead, 2575 size_t *pcbPostRead, unsigned fWrite) 1810 static int qedWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 1811 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 1812 size_t *pcbPostRead, unsigned fWrite) 2576 1813 { 2577 1814 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", … … 2615 1852 2616 1853 /* Get offset in image. */ 2617 rc = qedConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster, 2618 &offImage); 1854 rc = qedConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage); 2619 1855 if (RT_SUCCESS(rc)) 2620 1856 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, … … 2755 1991 } 2756 1992 2757 static int qed AsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)1993 static int qedFlush(void *pBackendData, PVDIOCTX pIoCtx) 2758 1994 { 2759 1995 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); … … 2767 2003 else 2768 2004 rc = VERR_INVALID_PARAMETER; 2005 2006 LogFlowFunc(("returns %Rrc\n", rc)); 2007 return rc; 2008 } 2009 2010 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 2011 static unsigned qedGetVersion(void *pBackendData) 2012 { 2013 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2014 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2015 2016 AssertPtr(pImage); 2017 2018 if (pImage) 2019 return 1; 2020 else 2021 return 0; 2022 } 2023 2024 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 2025 static uint64_t qedGetSize(void *pBackendData) 2026 { 2027 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2028 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2029 uint64_t cb = 0; 2030 2031 AssertPtr(pImage); 2032 2033 if (pImage && pImage->pStorage) 2034 cb = pImage->cbSize; 2035 2036 LogFlowFunc(("returns %llu\n", cb)); 2037 return cb; 2038 } 2039 2040 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 2041 static uint64_t qedGetFileSize(void *pBackendData) 2042 { 2043 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2044 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2045 uint64_t cb = 0; 2046 2047 AssertPtr(pImage); 2048 2049 if (pImage) 2050 { 2051 uint64_t cbFile; 2052 if (pImage->pStorage) 2053 { 2054 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 2055 if (RT_SUCCESS(rc)) 2056 cb += cbFile; 2057 } 2058 } 2059 2060 LogFlowFunc(("returns %lld\n", cb)); 2061 return cb; 2062 } 2063 2064 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 2065 static int qedGetPCHSGeometry(void *pBackendData, 2066 PVDGEOMETRY pPCHSGeometry) 2067 { 2068 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 2069 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2070 int rc; 2071 2072 AssertPtr(pImage); 2073 2074 if (pImage) 2075 { 2076 if (pImage->PCHSGeometry.cCylinders) 2077 { 2078 *pPCHSGeometry = pImage->PCHSGeometry; 2079 rc = VINF_SUCCESS; 2080 } 2081 else 2082 rc = VERR_VD_GEOMETRY_NOT_SET; 2083 } 2084 else 2085 rc = VERR_VD_NOT_OPENED; 2086 2087 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2088 return rc; 2089 } 2090 2091 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 2092 static int qedSetPCHSGeometry(void *pBackendData, 2093 PCVDGEOMETRY pPCHSGeometry) 2094 { 2095 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2096 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2097 int rc; 2098 2099 AssertPtr(pImage); 2100 2101 if (pImage) 2102 { 2103 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2104 { 2105 rc = VERR_VD_IMAGE_READ_ONLY; 2106 goto out; 2107 } 2108 2109 pImage->PCHSGeometry = *pPCHSGeometry; 2110 rc = VINF_SUCCESS; 2111 } 2112 else 2113 rc = VERR_VD_NOT_OPENED; 2114 2115 out: 2116 LogFlowFunc(("returns %Rrc\n", rc)); 2117 return rc; 2118 } 2119 2120 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 2121 static int qedGetLCHSGeometry(void *pBackendData, 2122 PVDGEOMETRY pLCHSGeometry) 2123 { 2124 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 2125 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2126 int rc; 2127 2128 AssertPtr(pImage); 2129 2130 if (pImage) 2131 { 2132 if (pImage->LCHSGeometry.cCylinders) 2133 { 2134 *pLCHSGeometry = pImage->LCHSGeometry; 2135 rc = VINF_SUCCESS; 2136 } 2137 else 2138 rc = VERR_VD_GEOMETRY_NOT_SET; 2139 } 2140 else 2141 rc = VERR_VD_NOT_OPENED; 2142 2143 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2144 return rc; 2145 } 2146 2147 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 2148 static int qedSetLCHSGeometry(void *pBackendData, 2149 PCVDGEOMETRY pLCHSGeometry) 2150 { 2151 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2152 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2153 int rc; 2154 2155 AssertPtr(pImage); 2156 2157 if (pImage) 2158 { 2159 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2160 { 2161 rc = VERR_VD_IMAGE_READ_ONLY; 2162 goto out; 2163 } 2164 2165 pImage->LCHSGeometry = *pLCHSGeometry; 2166 rc = VINF_SUCCESS; 2167 } 2168 else 2169 rc = VERR_VD_NOT_OPENED; 2170 2171 out: 2172 LogFlowFunc(("returns %Rrc\n", rc)); 2173 return rc; 2174 } 2175 2176 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 2177 static unsigned qedGetImageFlags(void *pBackendData) 2178 { 2179 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2180 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2181 unsigned uImageFlags; 2182 2183 AssertPtr(pImage); 2184 2185 if (pImage) 2186 uImageFlags = pImage->uImageFlags; 2187 else 2188 uImageFlags = 0; 2189 2190 LogFlowFunc(("returns %#x\n", uImageFlags)); 2191 return uImageFlags; 2192 } 2193 2194 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 2195 static unsigned qedGetOpenFlags(void *pBackendData) 2196 { 2197 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2198 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2199 unsigned uOpenFlags; 2200 2201 AssertPtr(pImage); 2202 2203 if (pImage) 2204 uOpenFlags = pImage->uOpenFlags; 2205 else 2206 uOpenFlags = 0; 2207 2208 LogFlowFunc(("returns %#x\n", uOpenFlags)); 2209 return uOpenFlags; 2210 } 2211 2212 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 2213 static int qedSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 2214 { 2215 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2216 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2217 int rc; 2218 2219 /* Image must be opened and the new flags must be valid. */ 2220 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 2221 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 2222 { 2223 rc = VERR_INVALID_PARAMETER; 2224 goto out; 2225 } 2226 2227 /* Implement this operation via reopening the image. */ 2228 rc = qedFreeImage(pImage, false); 2229 if (RT_FAILURE(rc)) 2230 goto out; 2231 rc = qedOpenImage(pImage, uOpenFlags); 2232 2233 out: 2234 LogFlowFunc(("returns %Rrc\n", rc)); 2235 return rc; 2236 } 2237 2238 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 2239 static int qedGetComment(void *pBackendData, char *pszComment, 2240 size_t cbComment) 2241 { 2242 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2243 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2244 int rc; 2245 2246 AssertPtr(pImage); 2247 2248 if (pImage) 2249 rc = VERR_NOT_SUPPORTED; 2250 else 2251 rc = VERR_VD_NOT_OPENED; 2252 2253 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 2254 return rc; 2255 } 2256 2257 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 2258 static int qedSetComment(void *pBackendData, const char *pszComment) 2259 { 2260 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2261 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2262 int rc; 2263 2264 AssertPtr(pImage); 2265 2266 if (pImage) 2267 { 2268 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2269 rc = VERR_VD_IMAGE_READ_ONLY; 2270 else 2271 rc = VERR_NOT_SUPPORTED; 2272 } 2273 else 2274 rc = VERR_VD_NOT_OPENED; 2275 2276 LogFlowFunc(("returns %Rrc\n", rc)); 2277 return rc; 2278 } 2279 2280 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 2281 static int qedGetUuid(void *pBackendData, PRTUUID pUuid) 2282 { 2283 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2284 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2285 int rc; 2286 2287 AssertPtr(pImage); 2288 2289 if (pImage) 2290 rc = VERR_NOT_SUPPORTED; 2291 else 2292 rc = VERR_VD_NOT_OPENED; 2293 2294 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2295 return rc; 2296 } 2297 2298 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 2299 static int qedSetUuid(void *pBackendData, PCRTUUID pUuid) 2300 { 2301 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2302 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2303 int rc; 2304 2305 LogFlowFunc(("%RTuuid\n", pUuid)); 2306 AssertPtr(pImage); 2307 2308 if (pImage) 2309 { 2310 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2311 rc = VERR_NOT_SUPPORTED; 2312 else 2313 rc = VERR_VD_IMAGE_READ_ONLY; 2314 } 2315 else 2316 rc = VERR_VD_NOT_OPENED; 2317 2318 LogFlowFunc(("returns %Rrc\n", rc)); 2319 return rc; 2320 } 2321 2322 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 2323 static int qedGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2324 { 2325 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2326 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2327 int rc; 2328 2329 AssertPtr(pImage); 2330 2331 if (pImage) 2332 rc = VERR_NOT_SUPPORTED; 2333 else 2334 rc = VERR_VD_NOT_OPENED; 2335 2336 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2337 return rc; 2338 } 2339 2340 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 2341 static int qedSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2342 { 2343 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2344 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2345 int rc; 2346 2347 AssertPtr(pImage); 2348 2349 if (pImage) 2350 { 2351 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2352 rc = VERR_NOT_SUPPORTED; 2353 else 2354 rc = VERR_VD_IMAGE_READ_ONLY; 2355 } 2356 else 2357 rc = VERR_VD_NOT_OPENED; 2358 2359 LogFlowFunc(("returns %Rrc\n", rc)); 2360 return rc; 2361 } 2362 2363 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 2364 static int qedGetParentUuid(void *pBackendData, PRTUUID pUuid) 2365 { 2366 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2367 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2368 int rc; 2369 2370 AssertPtr(pImage); 2371 2372 if (pImage) 2373 rc = VERR_NOT_SUPPORTED; 2374 else 2375 rc = VERR_VD_NOT_OPENED; 2376 2377 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2378 return rc; 2379 } 2380 2381 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 2382 static int qedSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2383 { 2384 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2385 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2386 int rc; 2387 2388 AssertPtr(pImage); 2389 2390 if (pImage) 2391 { 2392 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2393 rc = VERR_NOT_SUPPORTED; 2394 else 2395 rc = VERR_VD_IMAGE_READ_ONLY; 2396 } 2397 else 2398 rc = VERR_VD_NOT_OPENED; 2399 2400 LogFlowFunc(("returns %Rrc\n", rc)); 2401 return rc; 2402 } 2403 2404 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 2405 static int qedGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2406 { 2407 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2408 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2409 int rc; 2410 2411 AssertPtr(pImage); 2412 2413 if (pImage) 2414 rc = VERR_NOT_SUPPORTED; 2415 else 2416 rc = VERR_VD_NOT_OPENED; 2417 2418 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2419 return rc; 2420 } 2421 2422 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 2423 static int qedSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2424 { 2425 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2426 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2427 int rc; 2428 2429 AssertPtr(pImage); 2430 2431 if (pImage) 2432 { 2433 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2434 rc = VERR_NOT_SUPPORTED; 2435 else 2436 rc = VERR_VD_IMAGE_READ_ONLY; 2437 } 2438 else 2439 rc = VERR_VD_NOT_OPENED; 2440 2441 LogFlowFunc(("returns %Rrc\n", rc)); 2442 return rc; 2443 } 2444 2445 /** @copydoc VBOXHDDBACKEND::pfnDump */ 2446 static void qedDump(void *pBackendData) 2447 { 2448 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2449 2450 AssertPtr(pImage); 2451 if (pImage) 2452 { 2453 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 2454 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2455 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2456 pImage->cbSize / 512); 2457 } 2458 } 2459 2460 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */ 2461 static int qedGetParentFilename(void *pBackendData, char **ppszParentFilename) 2462 { 2463 int rc = VINF_SUCCESS; 2464 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2465 2466 AssertPtr(pImage); 2467 if (pImage) 2468 if (pImage->pszFilename) 2469 *ppszParentFilename = RTStrDup(pImage->pszBackingFilename); 2470 else 2471 rc = VERR_NOT_SUPPORTED; 2472 else 2473 rc = VERR_VD_NOT_OPENED; 2474 2475 LogFlowFunc(("returns %Rrc\n", rc)); 2476 return rc; 2477 } 2478 2479 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */ 2480 static int qedSetParentFilename(void *pBackendData, const char *pszParentFilename) 2481 { 2482 int rc = VINF_SUCCESS; 2483 PQEDIMAGE pImage = (PQEDIMAGE)pBackendData; 2484 2485 AssertPtr(pImage); 2486 if (pImage) 2487 { 2488 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2489 rc = VERR_VD_IMAGE_READ_ONLY; 2490 else if ( pImage->pszBackingFilename 2491 && (strlen(pszParentFilename) > pImage->cbBackingFilename)) 2492 rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */ 2493 else 2494 { 2495 if (pImage->pszBackingFilename) 2496 RTStrFree(pImage->pszBackingFilename); 2497 pImage->pszBackingFilename = RTStrDup(pszParentFilename); 2498 if (!pImage->pszBackingFilename) 2499 rc = VERR_NO_MEMORY; 2500 else 2501 { 2502 if (!pImage->offBackingFilename) 2503 { 2504 /* Allocate new cluster. */ 2505 uint64_t offData = qedClusterAllocate(pImage, 1); 2506 2507 Assert((offData & UINT32_MAX) == offData); 2508 pImage->offBackingFilename = (uint32_t)offData; 2509 pImage->cbBackingFilename = strlen(pszParentFilename); 2510 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, 2511 offData + pImage->cbCluster); 2512 } 2513 2514 if (RT_SUCCESS(rc)) 2515 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2516 pImage->offBackingFilename, 2517 pImage->pszBackingFilename, 2518 strlen(pImage->pszBackingFilename)); 2519 } 2520 } 2521 } 2522 else 2523 rc = VERR_VD_NOT_OPENED; 2769 2524 2770 2525 LogFlowFunc(("returns %Rrc\n", rc)); … … 2854 2609 /* pfnFlush */ 2855 2610 qedFlush, 2611 /* pfnDiscard */ 2612 NULL, 2856 2613 /* pfnGetVersion */ 2857 2614 qedGetVersion, … … 2906 2663 /* pfnSetParentFilename */ 2907 2664 qedSetParentFilename, 2908 /* pfnAsyncRead */2909 qedAsyncRead,2910 /* pfnAsyncWrite */2911 qedAsyncWrite,2912 /* pfnAsyncFlush */2913 qedAsyncFlush,2914 2665 /* pfnComposeLocation */ 2915 2666 genericFileComposeLocation, … … 2920 2671 /* pfnResize */ 2921 2672 qedResize, 2922 /* pfnDiscard */2923 NULL,2924 /* pfnAsyncDiscard */2925 NULL,2926 2673 /* pfnRepair */ 2927 2674 NULL -
trunk/src/VBox/Storage/RAW.cpp
r44233 r44252 602 602 603 603 /** @copydoc VBOXHDDBACKEND::pfnRead */ 604 static int rawRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 605 size_t cbToRead, size_t *pcbActuallyRead) 606 { 607 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 608 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 609 int rc; 610 611 AssertPtr(pImage); 612 Assert(uOffset % 512 == 0); 613 Assert(cbToRead % 512 == 0); 614 615 if ( uOffset + cbToRead > pImage->cbSize 616 || cbToRead == 0) 617 { 618 rc = VERR_INVALID_PARAMETER; 619 goto out; 620 } 621 622 /* For sequential access do not allow to go back. */ 623 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL 624 && uOffset < pImage->offAccess) 625 { 626 rc = VERR_INVALID_PARAMETER; 627 goto out; 628 } 629 630 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, 631 cbToRead); 632 pImage->offAccess = uOffset + cbToRead; 633 if (pcbActuallyRead) 634 *pcbActuallyRead = cbToRead; 635 636 out: 637 LogFlowFunc(("returns %Rrc\n", rc)); 604 static int rawRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 605 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 606 { 607 int rc = VINF_SUCCESS; 608 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 609 610 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset, 611 pIoCtx, cbRead); 612 if (RT_SUCCESS(rc)) 613 *pcbActuallyRead = cbRead; 614 638 615 return rc; 639 616 } 640 617 641 618 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 642 static int rawWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 643 size_t cbToWrite, size_t *pcbWriteProcess, 644 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 645 { 646 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 647 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 648 int rc; 649 650 AssertPtr(pImage); 651 Assert(uOffset % 512 == 0); 652 Assert(cbToWrite % 512 == 0); 653 654 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 655 { 656 rc = VERR_VD_IMAGE_READ_ONLY; 657 goto out; 658 } 659 660 if ( uOffset + cbToWrite > pImage->cbSize 661 || cbToWrite == 0) 662 { 663 rc = VERR_INVALID_PARAMETER; 664 goto out; 665 } 666 667 /* For sequential access do not allow to go back. */ 668 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL 669 && uOffset < pImage->offAccess) 670 { 671 rc = VERR_INVALID_PARAMETER; 672 goto out; 673 } 674 675 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, 676 cbToWrite); 677 pImage->offAccess = uOffset + cbToWrite; 678 if (pcbWriteProcess) 679 *pcbWriteProcess = cbToWrite; 680 681 out: 682 LogFlowFunc(("returns %Rrc\n", rc)); 619 static int rawWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 620 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 621 size_t *pcbPostRead, unsigned fWrite) 622 { 623 int rc = VINF_SUCCESS; 624 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 625 626 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset, 627 pIoCtx, cbWrite, NULL, NULL); 628 if (RT_SUCCESS(rc)) 629 { 630 *pcbWriteProcess = cbWrite; 631 *pcbPostRead = 0; 632 *pcbPreRead = 0; 633 } 634 683 635 return rc; 684 636 } 685 637 686 638 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 687 static int rawFlush(void *pBackendData) 688 { 689 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 690 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 691 int rc; 692 693 rc = rawFlushImage(pImage); 694 LogFlowFunc(("returns %Rrc\n", rc)); 639 static int rawFlush(void *pBackendData, PVDIOCTX pIoCtx) 640 { 641 int rc = VINF_SUCCESS; 642 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 643 644 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 645 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx, 646 NULL, NULL); 647 695 648 return rc; 696 649 } … … 1147 1100 } 1148 1101 1149 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */1150 static int rawAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,1151 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)1152 {1153 int rc = VINF_SUCCESS;1154 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;1155 1156 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,1157 pIoCtx, cbRead);1158 if (RT_SUCCESS(rc))1159 *pcbActuallyRead = cbRead;1160 1161 return rc;1162 }1163 1164 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */1165 static int rawAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,1166 PVDIOCTX pIoCtx,1167 size_t *pcbWriteProcess, size_t *pcbPreRead,1168 size_t *pcbPostRead, unsigned fWrite)1169 {1170 int rc = VINF_SUCCESS;1171 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;1172 1173 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset,1174 pIoCtx, cbWrite, NULL, NULL);1175 if (RT_SUCCESS(rc))1176 {1177 *pcbWriteProcess = cbWrite;1178 *pcbPostRead = 0;1179 *pcbPreRead = 0;1180 }1181 1182 return rc;1183 }1184 1185 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */1186 static int rawAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)1187 {1188 int rc = VINF_SUCCESS;1189 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;1190 1191 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))1192 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx,1193 NULL, NULL);1194 1195 return rc;1196 }1197 1102 1198 1103 … … 1227 1132 /* pfnFlush */ 1228 1133 rawFlush, 1134 /* pfnDiscard */ 1135 NULL, 1229 1136 /* pfnGetVersion */ 1230 1137 rawGetVersion, … … 1279 1186 /* pfnSetParentFilename */ 1280 1187 NULL, 1281 /* pfnAsyncRead */1282 rawAsyncRead,1283 /* pfnAsyncWrite */1284 rawAsyncWrite,1285 /* pfnAsyncFlush */1286 rawAsyncFlush,1287 1188 /* pfnComposeLocation */ 1288 1189 genericFileComposeLocation, … … 1293 1194 /* pfnResize */ 1294 1195 NULL, 1295 /* pfnDiscard */1296 NULL,1297 /* pfnAsyncDiscard */1298 NULL,1299 1196 /* pfnRepair */ 1300 1197 NULL -
trunk/src/VBox/Storage/VD.cpp
r44242 r44252 913 913 * If the block is not allocated read from override chain if present. 914 914 */ 915 rc = pImage->Backend->pfn AsyncRead(pImage->pBackendData,915 rc = pImage->Backend->pfnRead(pImage->pBackendData, 916 916 uOffset, cbThisRead, &IoCtx, 917 917 &cbThisRead); … … 923 923 pCurrImage = pCurrImage->pPrev) 924 924 { 925 rc = pCurrImage->Backend->pfn AsyncRead(pCurrImage->pBackendData,925 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 926 926 uOffset, cbThisRead, &IoCtx, 927 927 &cbThisRead); … … 1013 1013 * If the block is not allocated read from override chain if present. 1014 1014 */ 1015 rc = pImage->Backend->pfn AsyncRead(pImage->pBackendData,1015 rc = pImage->Backend->pfnRead(pImage->pBackendData, 1016 1016 uOffset, cbThisRead, &IoCtx, 1017 1017 &cbThisRead); … … 1026 1026 pCurrImage = pCurrImage->pPrev) 1027 1027 { 1028 rc = pCurrImage->Backend->pfn AsyncRead(pCurrImage->pBackendData,1028 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 1029 1029 uOffset, cbThisRead, 1030 1030 &IoCtx, &cbThisRead); … … 1161 1161 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL, 1162 1162 NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC); 1163 rc = pDisk->pLast->Backend->pfn AsyncDiscard(pDisk->pLast->pBackendData,1163 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, 1164 1164 &IoCtx, offStart, cbThis, NULL, 1165 1165 NULL, &cbThis, NULL, … … 1256 1256 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL, 1257 1257 NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC); 1258 rc = pDisk->pLast->Backend->pfn AsyncDiscard(pDisk->pLast->pBackendData,1258 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, 1259 1259 &IoCtx, offStart, 1260 1260 cbThisDiscard, &cbPreAllocated, … … 1313 1313 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL, 1314 1314 NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC); 1315 rc = pDisk->pLast->Backend->pfn AsyncDiscard(pDisk->pLast->pBackendData,1315 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, 1316 1316 &IoCtx, pBlock->Core.Key, 1317 1317 pBlock->cbDiscard, &cbPreAllocated, … … 1650 1650 } 1651 1651 1652 static size_t vdIoCtxCopyTo(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData) 1652 static size_t vdIoCtxCopyTo(PVDIOCTX pIoCtx, const uint8_t *pbData, size_t cbData) 1653 { 1654 return RTSgBufCopyFromBuf(&pIoCtx->Req.Io.SgBuf, pbData, cbData); 1655 } 1656 1657 static size_t vdIoCtxCopyFrom(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData) 1653 1658 { 1654 1659 return RTSgBufCopyToBuf(&pIoCtx->Req.Io.SgBuf, pbData, cbData); 1655 }1656 1657 1658 static size_t vdIoCtxCopyFrom(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData)1659 {1660 return RTSgBufCopyFromBuf(&pIoCtx->Req.Io.SgBuf, pbData, cbData);1661 1660 } 1662 1661 … … 2054 2053 * If the block is not allocated read from override chain if present. 2055 2054 */ 2056 rc = pCurrImage->Backend->pfn AsyncRead(pCurrImage->pBackendData,2055 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 2057 2056 uOffset, cbThisRead, 2058 2057 pIoCtx, &cbThisRead); … … 2064 2063 { 2065 2064 pCurrImage = pCurrImage->pPrev; 2066 rc = pCurrImage->Backend->pfn AsyncRead(pCurrImage->pBackendData,2065 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 2067 2066 uOffset, cbThisRead, 2068 2067 pIoCtx, &cbThisRead); … … 2161 2160 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_FLUSH, 0, 0, NULL, 2162 2161 NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC); 2163 pDisk->pLast->Backend->pfn AsyncFlush(pDisk->pLast->pBackendData, &IoCtx);2162 pDisk->pLast->Backend->pfnFlush(pDisk->pLast->pBackendData, &IoCtx); 2164 2163 } 2165 2164 } … … 2249 2248 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL, 2250 2249 &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC); 2251 rc = pImage->Backend->pfn AsyncWrite(pImage->pBackendData, uOffset - cbPreRead,2250 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset - cbPreRead, 2252 2251 cbPreRead + cbThisWrite + cbPostRead, 2253 2252 &IoCtx, NULL, &cbPreRead, &cbPostRead, 0); … … 2339 2338 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL, 2340 2339 &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC); 2341 rc = pImage->Backend->pfn AsyncWrite(pImage->pBackendData, uOffset - cbPreRead,2340 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset - cbPreRead, 2342 2341 cbPreRead + cbThisWrite + cbPostRead, 2343 2342 &IoCtx, NULL, &cbPreRead, &cbPostRead, 0); … … 2387 2386 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL, 2388 2387 &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC); 2389 rc = pImage->Backend->pfn AsyncWrite(pImage->pBackendData, uOffsetCur, cbThisWrite,2388 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffsetCur, cbThisWrite, 2390 2389 &IoCtx, &cbThisWrite, &cbPreRead, 2391 2390 &cbPostRead, fWrite); … … 2501 2500 2502 2501 /* Read the source data. */ 2503 rc = pImageFrom->Backend->pfn AsyncRead(pImageFrom->pBackendData,2502 rc = pImageFrom->Backend->pfnRead(pImageFrom->pBackendData, 2504 2503 uOffset, cbThisRead, &IoCtx, 2505 2504 &cbThisRead); … … 2514 2513 pCurrImage = pCurrImage->pPrev) 2515 2514 { 2516 rc = pCurrImage->Backend->pfn AsyncRead(pCurrImage->pBackendData,2515 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 2517 2516 uOffset, cbThisRead, 2518 2517 &IoCtx, &cbThisRead); … … 2607 2606 PVDIMAGE pImage = pIoCtx->Req.Io.pImageCur; 2608 2607 2609 rc = pImage->Backend->pfn AsyncFlush(pImage->pBackendData, pIoCtx);2608 rc = pImage->Backend->pfnFlush(pImage->pBackendData, pIoCtx); 2610 2609 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 2611 2610 rc = VINF_SUCCESS; … … 2736 2735 /* Write the full block to the virtual disk. */ 2737 2736 vdIoCtxChildReset(pIoCtxDst); 2738 rc = pImage->Backend->pfn AsyncWrite(pImage->pBackendData,2737 rc = pImage->Backend->pfnWrite(pImage->pBackendData, 2739 2738 uOffset - cbPreRead, 2740 2739 cbPreRead + cbThisWrite + cbPostRead, … … 2767 2766 2768 2767 LogFlowFunc(("pIoCtx=%#p\n", pIoCtx)); 2769 rc = pImage->Backend->pfn AsyncWrite(pImage->pBackendData,2768 rc = pImage->Backend->pfnWrite(pImage->pBackendData, 2770 2769 pIoCtx->Req.Io.uOffset - cbPreRead, 2771 2770 cbPreRead + cbThisWrite + cbPostRead, … … 2973 2972 fWrite = (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME) 2974 2973 ? 0 : VD_WRITE_NO_ALLOC; 2975 rc = pImage->Backend->pfn AsyncWrite(pImage->pBackendData, uOffset,2974 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset, 2976 2975 cbThisWrite, pIoCtx, 2977 2976 &cbThisWrite, &cbPreRead, … … 3100 3099 { 3101 3100 vdResetModifiedFlag(pDisk); 3102 rc = pImage->Backend->pfn AsyncFlush(pImage->pBackendData, pIoCtx);3101 rc = pImage->Backend->pfnFlush(pImage->pBackendData, pIoCtx); 3103 3102 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 3104 3103 rc = VINF_SUCCESS; … … 3129 3128 AssertPtr(pBlock); 3130 3129 3131 rc = pDisk->pLast->Backend->pfn AsyncDiscard(pDisk->pLast->pBackendData, pIoCtx,3130 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, pIoCtx, 3132 3131 pBlock->Core.Key, pBlock->cbDiscard, 3133 3132 &cbPreAllocated, &cbPostAllocated, … … 3211 3210 cbThis = (idxEnd - idxStart) * 512; 3212 3211 3213 rc = pDisk->pLast->Backend->pfn AsyncDiscard(pDisk->pLast->pBackendData, pIoCtx,3212 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, pIoCtx, 3214 3213 offStart, cbThis, NULL, NULL, &cbThis, 3215 3214 NULL, VD_DISCARD_MARK_UNUSED); … … 3268 3267 3269 3268 /* No block found, try to discard using the backend first. */ 3270 rc = pDisk->pLast->Backend->pfn AsyncDiscard(pDisk->pLast->pBackendData, pIoCtx,3269 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, pIoCtx, 3271 3270 offStart, cbThisDiscard, &cbPreAllocated, 3272 3271 &cbPostAllocated, &cbThisDiscard, … … 4750 4749 4751 4750 static size_t vdIOIntIoCtxCopyTo(void *pvUser, PVDIOCTX pIoCtx, 4752 void *pvBuf, size_t cbBuf)4751 const void *pvBuf, size_t cbBuf) 4753 4752 { 4754 4753 PVDIO pVDIo = (PVDIO)pvUser; … … 6958 6957 fLockWrite = true; 6959 6958 6960 rc = pImageTo->Backend->pfn AsyncRead(pImageTo->pBackendData,6959 rc = pImageTo->Backend->pfnRead(pImageTo->pBackendData, 6961 6960 uOffset, cbThisRead, 6962 6961 &IoCtx, &cbThisRead); … … 6971 6970 pCurrImage = pCurrImage->pPrev) 6972 6971 { 6973 rc = pCurrImage->Backend->pfn AsyncRead(pCurrImage->pBackendData,6972 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 6974 6973 uOffset, cbThisRead, 6975 6974 &IoCtx, &cbThisRead); … … 7097 7096 pCurrImage = pCurrImage->pPrev) 7098 7097 { 7099 rc = pCurrImage->Backend->pfn AsyncRead(pCurrImage->pBackendData,7098 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 7100 7099 uOffset, cbThisRead, 7101 7100 &IoCtx, &cbThisRead); … … 8298 8297 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_FLUSH, 0, 0, NULL, 8299 8298 NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC); 8300 rc = pImage->Backend->pfn AsyncFlush(pImage->pBackendData, &IoCtx);8299 rc = pImage->Backend->pfnFlush(pImage->pBackendData, &IoCtx); 8301 8300 8302 8301 #if 0 /** @todo: Change cache implementation. */ -
trunk/src/VBox/Storage/VDI.cpp
r44242 r44252 1062 1062 * Internal: Flush the image file to disk - async version. 1063 1063 */ 1064 static int vdiFlushImage Async(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx)1064 static int vdiFlushImageIoCtx(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) 1065 1065 { 1066 1066 int rc = VINF_SUCCESS; … … 1078 1078 } 1079 1079 1080 return rc;1081 }1082 1083 /**1084 * Internal: Discard a whole block from the image filling the created hole with1085 * data from another block.1086 *1087 * @returns VBox status code.1088 * @param pImage VDI image instance data.1089 * @param uBlock The block to discard.1090 * @param pvBlock Memory to use for the I/O.1091 */1092 static int vdiDiscardBlock(PVDIIMAGEDESC pImage, unsigned uBlock, void *pvBlock)1093 {1094 int rc = VINF_SUCCESS;1095 uint64_t cbImage;1096 unsigned idxLastBlock = getImageBlocksAllocated(&pImage->Header) - 1;1097 unsigned uBlockLast = pImage->paBlocksRev[idxLastBlock];1098 VDIIMAGEBLOCKPOINTER ptrBlockDiscard = pImage->paBlocks[uBlock];1099 1100 LogFlowFunc(("pImage=%#p uBlock=%u pvBlock=%#p\n",1101 pImage, uBlock, pvBlock));1102 1103 pImage->paBlocksRev[idxLastBlock] = VDI_IMAGE_BLOCK_FREE;1104 1105 do1106 {1107 /*1108 * The block is empty, remove it.1109 * Read the last block of the image first.1110 */1111 if (idxLastBlock != ptrBlockDiscard)1112 {1113 uint64_t u64Offset;1114 1115 LogFlowFunc(("Moving block [%u]=%u into [%u]=%u\n",1116 uBlockLast, idxLastBlock, uBlock, pImage->paBlocks[uBlock]));1117 1118 u64Offset = (uint64_t)idxLastBlock * pImage->cbTotalBlockData + pImage->offStartData;1119 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,1120 pvBlock, pImage->cbTotalBlockData);1121 if (RT_FAILURE(rc))1122 break;1123 1124 /* Write to the now unallocated block. */1125 u64Offset = (uint64_t)ptrBlockDiscard * pImage->cbTotalBlockData + pImage->offStartData;1126 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset,1127 pvBlock, pImage->cbTotalBlockData);1128 if (RT_FAILURE(rc))1129 break;1130 1131 /* Update block and reverse block tables. */1132 pImage->paBlocks[uBlockLast] = ptrBlockDiscard;1133 pImage->paBlocksRev[ptrBlockDiscard] = uBlockLast;1134 rc = vdiUpdateBlockInfo(pImage, uBlockLast);1135 if (RT_FAILURE(rc))1136 break;1137 }1138 else1139 LogFlowFunc(("Discard last block [%u]=%u\n", uBlock, pImage->paBlocks[uBlock]));1140 1141 pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;1142 1143 /* Update the block pointers. */1144 setImageBlocksAllocated(&pImage->Header, idxLastBlock);1145 rc = vdiUpdateBlockInfo(pImage, uBlock);1146 if (RT_FAILURE(rc))1147 break;1148 1149 pImage->cbImage -= pImage->cbTotalBlockData;1150 LogFlowFunc(("Set new size %llu\n", pImage->cbImage));1151 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->cbImage);1152 } while (0);1153 1154 LogFlowFunc(("returns rc=%Rrc\n", rc));1155 1080 return rc; 1156 1081 } … … 1353 1278 * @param rcReq Status code for the completed request. 1354 1279 */ 1355 static DECLCALLBACK(int) vdi AsyncBlockAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)1280 static DECLCALLBACK(int) vdiBlockAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 1356 1281 { 1357 1282 int rc = VINF_SUCCESS; … … 1621 1546 } 1622 1547 1623 /** @copydoc VBOXHDDBACKEND::pfnRead */ 1624 static int vdiRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 1625 size_t cbToRead, size_t *pcbActuallyRead) 1626 { 1627 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));1548 static int vdiRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 1549 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1550 { 1551 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1552 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 1628 1553 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 1629 1554 unsigned uBlock; … … 1636 1561 1637 1562 if ( uOffset + cbToRead > getImageDiskSize(&pImage->Header) 1638 || !VALID_PTR(p vBuf)1563 || !VALID_PTR(pIoCtx) 1639 1564 || !cbToRead) 1640 1565 { … … 1655 1580 else if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO) 1656 1581 { 1657 memset(pvBuf, 0, cbToRead); 1582 size_t cbSet; 1583 1584 cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); 1585 Assert(cbSet == cbToRead); 1586 1658 1587 rc = VINF_SUCCESS; 1659 1588 } … … 1665 1594 1666 1595 if (u64Offset + cbToRead <= pImage->cbImage) 1667 rc = vdIfIoIntFileRead Sync(pImage->pIfIo, pImage->pStorage, u64Offset,1668 p vBuf, cbToRead);1596 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, u64Offset, 1597 pIoCtx, cbToRead); 1669 1598 else 1670 1599 { 1671 1600 LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n", 1672 1601 u64Offset, pImage->pszFilename, pImage->cbImage)); 1673 memset(pvBuf, 0, cbToRead);1602 vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); 1674 1603 rc = VERR_VD_READ_OUT_OF_RANGE; 1675 1604 } … … 1684 1613 } 1685 1614 1686 /**@copydoc VBOXHDDBACKEND::pfnWrite */ 1687 static int vdiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,1688 size_t cbToWrite, size_t *pcbWriteProcess,1689 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 1690 { 1691 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));1615 static int vdiWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 1616 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 1617 size_t *pcbPostRead, unsigned fWrite) 1618 { 1619 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 1620 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 1692 1621 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 1693 1622 unsigned uBlock; … … 1705 1634 } 1706 1635 1707 if (!VALID_PTR(p vBuf) || !cbToWrite)1636 if (!VALID_PTR(pIoCtx) || !cbToWrite) 1708 1637 { 1709 1638 rc = VERR_INVALID_PARAMETER; … … 1736 1665 * (which also means that it's a zero block. Don't need to write 1737 1666 * anything to this block if the data consists of just zeroes. */ 1738 Assert(!(cbToWrite % 4)); 1739 Assert(cbToWrite * 8 <= UINT32_MAX); 1740 if (ASMBitFirstSet((volatile void *)pvBuf, (uint32_t)cbToWrite * 8) == -1) 1667 if (vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbToWrite, true)) 1741 1668 { 1742 1669 pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO; … … 1753 1680 * Allocate block and write data. */ 1754 1681 Assert(!offWrite); 1682 PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)RTMemAllocZ(sizeof(VDIASYNCBLOCKALLOC)); 1683 if (!pBlockAlloc) 1684 { 1685 rc = VERR_NO_MEMORY; 1686 break; 1687 } 1688 1755 1689 unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header); 1756 1690 uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData 1757 1691 + (pImage->offStartData + pImage->offStartBlockData); 1758 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1759 u64Offset, pvBuf, cbToWrite); 1760 if (RT_FAILURE(rc)) 1761 goto out; 1762 pImage->paBlocks[uBlock] = cBlocksAllocated; 1763 1764 if (pImage->paBlocksRev) 1765 pImage->paBlocksRev[cBlocksAllocated] = uBlock; 1766 1767 setImageBlocksAllocated(&pImage->Header, cBlocksAllocated + 1); 1768 1769 rc = vdiUpdateBlockInfo(pImage, uBlock); 1770 if (RT_FAILURE(rc)) 1771 goto out; 1772 1773 pImage->cbImage += cbToWrite; 1692 1693 pBlockAlloc->cBlocksAllocated = cBlocksAllocated; 1694 pBlockAlloc->uBlock = uBlock; 1695 1774 1696 *pcbPreRead = 0; 1775 1697 *pcbPostRead = 0; 1698 1699 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, 1700 u64Offset, pIoCtx, cbToWrite, 1701 vdiBlockAllocUpdate, pBlockAlloc); 1702 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1703 break; 1704 else if (RT_FAILURE(rc)) 1705 { 1706 RTMemFree(pBlockAlloc); 1707 break; 1708 } 1709 1710 rc = vdiBlockAllocUpdate(pImage, pIoCtx, pBlockAlloc, rc); 1776 1711 } 1777 1712 else … … 1789 1724 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData 1790 1725 + (pImage->offStartData + pImage->offStartBlockData + offWrite); 1791 rc = vdIfIoIntFileWrite Sync(pImage->pIfIo, pImage->pStorage, u64Offset,1792 pvBuf, cbToWrite);1726 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, 1727 u64Offset, pIoCtx, cbToWrite, NULL, NULL); 1793 1728 } 1794 1729 } while (0); … … 1802 1737 } 1803 1738 1804 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1805 static int vdiFlush(void *pBackendData) 1739 static int vdiFlush(void *pBackendData, PVDIOCTX pIoCtx) 1806 1740 { 1807 1741 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); … … 1811 1745 Assert(pImage); 1812 1746 1813 vdiFlushImage(pImage);1747 rc = vdiFlushImageIoCtx(pImage, pIoCtx); 1814 1748 LogFlowFunc(("returns %Rrc\n", rc)); 1815 1749 return rc; … … 2432 2366 } 2433 2367 2434 static int vdiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,2435 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)2436 {2437 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",2438 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));2439 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;2440 unsigned uBlock;2441 unsigned offRead;2442 int rc;2443 2444 AssertPtr(pImage);2445 Assert(!(uOffset % 512));2446 Assert(!(cbToRead % 512));2447 2448 if ( uOffset + cbToRead > getImageDiskSize(&pImage->Header)2449 || !VALID_PTR(pIoCtx)2450 || !cbToRead)2451 {2452 rc = VERR_INVALID_PARAMETER;2453 goto out;2454 }2455 2456 /* Calculate starting block number and offset inside it. */2457 uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index);2458 offRead = (unsigned)uOffset & pImage->uBlockMask;2459 2460 /* Clip read range to at most the rest of the block. */2461 cbToRead = RT_MIN(cbToRead, getImageBlockSize(&pImage->Header) - offRead);2462 Assert(!(cbToRead % 512));2463 2464 if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_FREE)2465 rc = VERR_VD_BLOCK_FREE;2466 else if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO)2467 {2468 size_t cbSet;2469 2470 cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);2471 Assert(cbSet == cbToRead);2472 2473 rc = VINF_SUCCESS;2474 }2475 else2476 {2477 /* Block present in image file, read relevant data. */2478 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData2479 + (pImage->offStartData + pImage->offStartBlockData + offRead);2480 2481 if (u64Offset + cbToRead <= pImage->cbImage)2482 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, u64Offset,2483 pIoCtx, cbToRead);2484 else2485 {2486 LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n",2487 u64Offset, pImage->pszFilename, pImage->cbImage));2488 vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);2489 rc = VERR_VD_READ_OUT_OF_RANGE;2490 }2491 }2492 2493 if (pcbActuallyRead)2494 *pcbActuallyRead = cbToRead;2495 2496 out:2497 LogFlowFunc(("returns %Rrc\n", rc));2498 return rc;2499 }2500 2501 static int vdiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,2502 PVDIOCTX pIoCtx,2503 size_t *pcbWriteProcess, size_t *pcbPreRead,2504 size_t *pcbPostRead, unsigned fWrite)2505 {2506 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",2507 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));2508 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;2509 unsigned uBlock;2510 unsigned offWrite;2511 int rc = VINF_SUCCESS;2512 2513 AssertPtr(pImage);2514 Assert(!(uOffset % 512));2515 Assert(!(cbToWrite % 512));2516 2517 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)2518 {2519 rc = VERR_VD_IMAGE_READ_ONLY;2520 goto out;2521 }2522 2523 if (!VALID_PTR(pIoCtx) || !cbToWrite)2524 {2525 rc = VERR_INVALID_PARAMETER;2526 goto out;2527 }2528 2529 /* No size check here, will do that later. For dynamic images which are2530 * not multiples of the block size in length, this would prevent writing to2531 * the last block. */2532 2533 /* Calculate starting block number and offset inside it. */2534 uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index);2535 offWrite = (unsigned)uOffset & pImage->uBlockMask;2536 2537 /* Clip write range to at most the rest of the block. */2538 cbToWrite = RT_MIN(cbToWrite, getImageBlockSize(&pImage->Header) - offWrite);2539 Assert(!(cbToWrite % 512));2540 2541 do2542 {2543 if (!IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[uBlock]))2544 {2545 /* Block is either free or zero. */2546 if ( !(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_ZEROES)2547 && ( pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO2548 || cbToWrite == getImageBlockSize(&pImage->Header)))2549 {2550 /* If the destination block is unallocated at this point, it's2551 * either a zero block or a block which hasn't been used so far2552 * (which also means that it's a zero block. Don't need to write2553 * anything to this block if the data consists of just zeroes. */2554 if (vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbToWrite, true))2555 {2556 pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;2557 *pcbPreRead = 0;2558 *pcbPostRead = 0;2559 break;2560 }2561 }2562 2563 if ( cbToWrite == getImageBlockSize(&pImage->Header)2564 && !(fWrite & VD_WRITE_NO_ALLOC))2565 {2566 /* Full block write to previously unallocated block.2567 * Allocate block and write data. */2568 Assert(!offWrite);2569 PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)RTMemAllocZ(sizeof(VDIASYNCBLOCKALLOC));2570 if (!pBlockAlloc)2571 {2572 rc = VERR_NO_MEMORY;2573 break;2574 }2575 2576 unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header);2577 uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData2578 + (pImage->offStartData + pImage->offStartBlockData);2579 2580 pBlockAlloc->cBlocksAllocated = cBlocksAllocated;2581 pBlockAlloc->uBlock = uBlock;2582 2583 *pcbPreRead = 0;2584 *pcbPostRead = 0;2585 2586 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,2587 u64Offset, pIoCtx, cbToWrite,2588 vdiAsyncBlockAllocUpdate, pBlockAlloc);2589 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)2590 break;2591 else if (RT_FAILURE(rc))2592 {2593 RTMemFree(pBlockAlloc);2594 break;2595 }2596 2597 rc = vdiAsyncBlockAllocUpdate(pImage, pIoCtx, pBlockAlloc, rc);2598 }2599 else2600 {2601 /* Trying to do a partial write to an unallocated block. Don't do2602 * anything except letting the upper layer know what to do. */2603 *pcbPreRead = offWrite % getImageBlockSize(&pImage->Header);2604 *pcbPostRead = getImageBlockSize(&pImage->Header) - cbToWrite - *pcbPreRead;2605 rc = VERR_VD_BLOCK_FREE;2606 }2607 }2608 else2609 {2610 /* Block present in image file, write relevant data. */2611 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData2612 + (pImage->offStartData + pImage->offStartBlockData + offWrite);2613 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,2614 u64Offset, pIoCtx, cbToWrite, NULL, NULL);2615 }2616 } while (0);2617 2618 if (pcbWriteProcess)2619 *pcbWriteProcess = cbToWrite;2620 2621 out:2622 LogFlowFunc(("returns %Rrc\n", rc));2623 return rc;2624 }2625 2626 static int vdiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)2627 {2628 LogFlowFunc(("pBackendData=%#p\n", pBackendData));2629 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;2630 int rc = VINF_SUCCESS;2631 2632 Assert(pImage);2633 2634 rc = vdiFlushImageAsync(pImage, pIoCtx);2635 LogFlowFunc(("returns %Rrc\n", rc));2636 return rc;2637 }2638 2639 2368 /** @copydoc VBOXHDDBACKEND::pfnCompact */ 2640 2369 static int vdiCompact(void *pBackendData, unsigned uPercentStart, … … 3088 2817 } 3089 2818 3090 3091 2819 /** @copydoc VBOXHDDBACKEND::pfnDiscard */ 3092 static DECLCALLBACK(int) vdiDiscard(void *pBackendData, 3093 uint64_t uOffset, size_t cbDiscard, 3094 size_t *pcbPreAllocated, 3095 size_t *pcbPostAllocated, 3096 size_t *pcbActuallyDiscarded, 3097 void **ppbmAllocationBitmap, 3098 unsigned fDiscard) 3099 { 3100 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 3101 unsigned uBlock; 3102 unsigned offDiscard; 3103 int rc = VINF_SUCCESS; 3104 void *pvBlock = NULL; 3105 3106 LogFlowFunc(("pBackendData=%#p uOffset=%llu cbDiscard=%zu pcbPreAllocated=%#p pcbPostAllocated=%#p pcbActuallyDiscarded=%#p ppbmAllocationBitmap=%#p fDiscard=%#x\n", 3107 pBackendData, uOffset, cbDiscard, pcbPreAllocated, pcbPostAllocated, pcbActuallyDiscarded, ppbmAllocationBitmap, fDiscard)); 3108 3109 AssertPtr(pImage); 3110 Assert(!(uOffset % 512)); 3111 Assert(!(cbDiscard % 512)); 3112 3113 AssertMsgReturn(!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY), 3114 ("Image is readonly\n"), VERR_VD_IMAGE_READ_ONLY); 3115 AssertMsgReturn( uOffset + cbDiscard <= getImageDiskSize(&pImage->Header) 3116 && cbDiscard, 3117 ("Invalid parameters uOffset=%llu cbDiscard=%zu\n", 3118 uOffset, cbDiscard), 3119 VERR_INVALID_PARAMETER); 3120 3121 do 3122 { 3123 AssertMsgBreakStmt(!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY), 3124 ("Image is opened readonly\n"), 3125 rc = VERR_VD_IMAGE_READ_ONLY); 3126 3127 AssertMsgBreakStmt(cbDiscard, 3128 ("cbDiscard=%u\n", cbDiscard), 3129 rc = VERR_INVALID_PARAMETER); 3130 3131 /* Calculate starting block number and offset inside it. */ 3132 uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index); 3133 offDiscard = (unsigned)uOffset & pImage->uBlockMask; 3134 3135 /* Clip range to at most the rest of the block. */ 3136 cbDiscard = RT_MIN(cbDiscard, getImageBlockSize(&pImage->Header) - offDiscard); 3137 Assert(!(cbDiscard % 512)); 3138 3139 if (pcbPreAllocated) 3140 *pcbPreAllocated = 0; 3141 3142 if (pcbPostAllocated) 3143 *pcbPostAllocated = 0; 3144 3145 if (IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[uBlock])) 3146 { 3147 uint8_t *pbBlockData; 3148 size_t cbPreAllocated, cbPostAllocated; 3149 3150 cbPreAllocated = offDiscard % getImageBlockSize(&pImage->Header); 3151 cbPostAllocated = getImageBlockSize(&pImage->Header) - cbDiscard - cbPreAllocated; 3152 3153 /* Read the block data. */ 3154 pvBlock = RTMemAlloc(pImage->cbTotalBlockData); 3155 if (!pvBlock) 3156 { 3157 rc = VERR_NO_MEMORY; 3158 break; 3159 } 3160 3161 if (!cbPreAllocated && !cbPostAllocated) 3162 { 3163 /* 3164 * Discarding a whole block, don't check for allocated sectors. 3165 * It is possible to just remove the whole block which avoids 3166 * one read and checking the whole block for data. 3167 */ 3168 rc = vdiDiscardBlock(pImage, uBlock, pvBlock); 3169 } 3170 else 3171 { 3172 /* Read data. */ 3173 pbBlockData = (uint8_t *)pvBlock + pImage->offStartBlockData; 3174 3175 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData; 3176 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, 3177 pvBlock, pImage->cbTotalBlockData); 3178 if (RT_FAILURE(rc)) 3179 break; 3180 3181 /* Clear data. */ 3182 memset(pbBlockData + offDiscard , 0, cbDiscard); 3183 3184 Assert(!(cbDiscard % 4)); 3185 Assert(cbDiscard * 8 <= UINT32_MAX); 3186 if (ASMBitFirstSet((volatile void *)pbBlockData, getImageBlockSize(&pImage->Header) * 8) == -1) 3187 rc = vdiDiscardBlock(pImage, uBlock, pvBlock); 3188 else if (fDiscard & VD_DISCARD_MARK_UNUSED) 3189 { 3190 /* Write changed data to the image. */ 3191 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset + offDiscard, 3192 pbBlockData + offDiscard, cbDiscard); 3193 } 3194 else 3195 { 3196 /* Block has data, create allocation bitmap. */ 3197 *pcbPreAllocated = cbPreAllocated; 3198 *pcbPostAllocated = cbPostAllocated; 3199 *ppbmAllocationBitmap = vdiAllocationBitmapCreate(pbBlockData, getImageBlockSize(&pImage->Header)); 3200 if (RT_UNLIKELY(!*ppbmAllocationBitmap)) 3201 rc = VERR_NO_MEMORY; 3202 else 3203 rc = VERR_VD_DISCARD_ALIGNMENT_NOT_MET; 3204 } 3205 } /* if: no complete block discarded */ 3206 } /* if: Block is allocated. */ 3207 /* else: nothing to do. */ 3208 } while (0); 3209 3210 if (pcbActuallyDiscarded) 3211 *pcbActuallyDiscarded = cbDiscard; 3212 3213 if (pvBlock) 3214 RTMemFree(pvBlock); 3215 3216 LogFlowFunc(("returns %Rrc\n", rc)); 3217 return rc; 3218 } 3219 3220 /** @copydoc VBOXHDDBACKEND::pfnDiscard */ 3221 static DECLCALLBACK(int) vdiAsyncDiscard(void *pBackendData, PVDIOCTX pIoCtx, 2820 static DECLCALLBACK(int) vdiDiscard(void *pBackendData, PVDIOCTX pIoCtx, 3222 2821 uint64_t uOffset, size_t cbDiscard, 3223 2822 size_t *pcbPreAllocated, … … 3602 3201 /* pfnFlush */ 3603 3202 vdiFlush, 3203 /* pfnDiscard */ 3204 vdiDiscard, 3604 3205 /* pfnGetVersion */ 3605 3206 vdiGetVersion, … … 3654 3255 /* pfnSetParentFilename */ 3655 3256 NULL, 3656 /* pfnAsyncRead */3657 vdiAsyncRead,3658 /* pfnAsyncWrite */3659 vdiAsyncWrite,3660 /* pfnAsyncFlush */3661 vdiAsyncFlush,3662 3257 /* pfnComposeLocation */ 3663 3258 genericFileComposeLocation, … … 3668 3263 /* pfnResize */ 3669 3264 vdiResize, 3670 /* pfnDiscard */3671 vdiDiscard,3672 /* pfnAsyncDiscard */3673 vdiAsyncDiscard,3674 3265 /* pfnRepair */ 3675 3266 vdiRepair -
trunk/src/VBox/Storage/VHD.cpp
r44233 r44252 1451 1451 1452 1452 /** @copydoc VBOXHDDBACKEND::pfnRead */ 1453 static int vhdRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 1454 size_t cbBuf, size_t *pcbActuallyRead) 1455 { 1456 LogFlowFunc(("pBackendData=%p uOffset=%#llu pvBuf=%p cbBuf=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbActuallyRead)); 1457 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1458 int rc = VINF_SUCCESS; 1459 1460 if (uOffset + cbBuf > pImage->cbSize) 1461 { 1462 rc = VERR_INVALID_PARAMETER; 1463 goto out; 1464 } 1465 1466 /* 1467 * If we have a dynamic disk image, we need to find the data block and sector to read. 1468 */ 1469 if (pImage->pBlockAllocationTable) 1470 { 1471 /* 1472 * Get the data block first. 1473 */ 1474 uint32_t cBlockAllocationTableEntry = (uOffset / VHD_SECTOR_SIZE) / pImage->cSectorsPerDataBlock; 1475 uint32_t cBATEntryIndex = (uOffset / VHD_SECTOR_SIZE) % pImage->cSectorsPerDataBlock; 1476 uint64_t uVhdOffset; 1477 1478 LogFlowFunc(("cBlockAllocationTableEntry=%u cBatEntryIndex=%u\n", cBlockAllocationTableEntry, cBATEntryIndex)); 1479 LogFlowFunc(("BlockAllocationEntry=%u\n", pImage->pBlockAllocationTable[cBlockAllocationTableEntry])); 1480 1481 /* 1482 * Clip read range to remain in this data block. 1483 */ 1484 cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE))); 1485 1486 /* 1487 * If the block is not allocated the content of the entry is ~0 1488 */ 1489 if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U) 1490 rc = VERR_VD_BLOCK_FREE; 1491 else 1492 { 1493 uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE; 1494 LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf)); 1495 1496 /* Read in the block's bitmap. */ 1497 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1498 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 1499 pImage->pu8Bitmap, pImage->cbDataBlockBitmap); 1500 if (RT_SUCCESS(rc)) 1501 { 1502 uint32_t cSectors = 0; 1503 1504 if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 1505 { 1506 cBATEntryIndex++; 1507 cSectors = 1; 1508 1509 /* 1510 * The first sector being read is marked dirty, read as much as we 1511 * can from child. Note that only sectors that are marked dirty 1512 * must be read from child. 1513 */ 1514 while ( (cSectors < (cbBuf / VHD_SECTOR_SIZE)) 1515 && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 1516 { 1517 cBATEntryIndex++; 1518 cSectors++; 1519 } 1520 1521 cbBuf = cSectors * VHD_SECTOR_SIZE; 1522 1523 LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf)); 1524 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1525 uVhdOffset, pvBuf, cbBuf); 1526 } 1527 else 1528 { 1529 /* 1530 * The first sector being read is marked clean, so we should read from 1531 * our parent instead, but only as much as there are the following 1532 * clean sectors, because the block may still contain dirty sectors 1533 * further on. We just need to compute the number of clean sectors 1534 * and pass it to our caller along with the notification that they 1535 * should be read from the parent. 1536 */ 1537 cBATEntryIndex++; 1538 cSectors = 1; 1539 1540 while ( (cSectors < (cbBuf / VHD_SECTOR_SIZE)) 1541 && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 1542 { 1543 cBATEntryIndex++; 1544 cSectors++; 1545 } 1546 1547 cbBuf = cSectors * VHD_SECTOR_SIZE; 1548 LogFunc(("Sectors free: uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf)); 1549 rc = VERR_VD_BLOCK_FREE; 1550 } 1551 } 1552 else 1553 AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc)); 1554 } 1555 } 1556 else 1557 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, cbBuf); 1558 1559 if ( RT_SUCCESS(rc) 1560 || rc == VERR_VD_BLOCK_FREE) 1561 { 1562 if (pcbActuallyRead) 1563 *pcbActuallyRead = cbBuf; 1564 1565 Log2(("vhdRead: off=%#llx pvBuf=%p cbBuf=%d\n", uOffset, pvBuf, cbBuf)); 1566 } 1567 1568 out: 1569 LogFlowFunc(("returns %Rrc\n", rc)); 1570 return rc; 1571 } 1572 1573 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1574 static int vhdWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 1575 size_t cbBuf, size_t *pcbWriteProcess, 1576 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 1577 { 1578 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess)); 1579 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1580 int rc = VINF_SUCCESS; 1581 1582 LogFlowFunc(("pBackendData=%p uOffset=%llu pvBuf=%p cbBuf=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n", 1583 pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite)); 1584 1585 AssertPtr(pImage); 1586 Assert(uOffset % VHD_SECTOR_SIZE == 0); 1587 Assert(cbBuf % VHD_SECTOR_SIZE == 0); 1588 1589 if (pImage->pBlockAllocationTable) 1590 { 1591 /* 1592 * Get the data block first. 1593 */ 1594 uint32_t cSector = uOffset / VHD_SECTOR_SIZE; 1595 uint32_t cBlockAllocationTableEntry = cSector / pImage->cSectorsPerDataBlock; 1596 uint32_t cBATEntryIndex = cSector % pImage->cSectorsPerDataBlock; 1597 uint64_t uVhdOffset; 1598 1599 /* 1600 * Clip write range. 1601 */ 1602 cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE))); 1603 1604 /* 1605 * If the block is not allocated the content of the entry is ~0 1606 * and we need to allocate a new block. Note that while blocks are 1607 * allocated with a relatively big granularity, each sector has its 1608 * own bitmap entry, indicating whether it has been written or not. 1609 * So that means for the purposes of the higher level that the 1610 * granularity is invisible. This means there's no need to return 1611 * VERR_VD_BLOCK_FREE unless the block hasn't been allocated yet. 1612 */ 1613 if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U) 1614 { 1615 /* Check if the block allocation should be suppressed. */ 1616 if (fWrite & VD_WRITE_NO_ALLOC) 1617 { 1618 *pcbPreRead = cBATEntryIndex * VHD_SECTOR_SIZE; 1619 *pcbPostRead = pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE - cbBuf - *pcbPreRead; 1620 1621 if (pcbWriteProcess) 1622 *pcbWriteProcess = cbBuf; 1623 rc = VERR_VD_BLOCK_FREE; 1624 goto out; 1625 } 1626 1627 size_t cbNewBlock = pImage->cbDataBlock + (pImage->cDataBlockBitmapSectors * VHD_SECTOR_SIZE); 1628 uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(cbNewBlock); 1629 1630 if (!pNewBlock) 1631 { 1632 rc = VERR_NO_MEMORY; 1633 goto out; 1634 } 1635 1636 /* 1637 * Write the new block at the current end of the file. 1638 */ 1639 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->uCurrentEndOfFile, 1640 pNewBlock, cbNewBlock); 1641 AssertRC(rc); 1642 1643 /* 1644 * Set the new end of the file and link the new block into the BAT. 1645 */ 1646 pImage->pBlockAllocationTable[cBlockAllocationTableEntry] = pImage->uCurrentEndOfFile / VHD_SECTOR_SIZE; 1647 pImage->uCurrentEndOfFile += cbNewBlock; 1648 RTMemFree(pNewBlock); 1649 1650 /* Write the updated BAT and the footer to remain in a consistent state. */ 1651 rc = vhdFlushImage(pImage); 1652 AssertRC(rc); 1653 } 1654 1655 /* 1656 * Calculate the real offset in the file. 1657 */ 1658 uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE; 1659 1660 /* Write data. */ 1661 vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uVhdOffset, 1662 pvBuf, cbBuf); 1663 1664 /* Read in the block's bitmap. */ 1665 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1666 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 1667 pImage->pu8Bitmap, pImage->cbDataBlockBitmap); 1668 if (RT_SUCCESS(rc)) 1669 { 1670 bool fChanged = false; 1671 1672 /* Set the bits for all sectors having been written. */ 1673 for (uint32_t iSector = 0; iSector < (cbBuf / VHD_SECTOR_SIZE); iSector++) 1674 { 1675 fChanged |= vhdBlockBitmapSectorSet(pImage, pImage->pu8Bitmap, cBATEntryIndex); 1676 cBATEntryIndex++; 1677 } 1678 1679 if (fChanged) 1680 { 1681 /* Write the bitmap back. */ 1682 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 1683 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 1684 pImage->pu8Bitmap, pImage->cbDataBlockBitmap); 1685 } 1686 } 1687 } 1688 else 1689 { 1690 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, cbBuf); 1691 } 1692 1693 if (pcbWriteProcess) 1694 *pcbWriteProcess = cbBuf; 1695 1696 /* Stay on the safe side. Do not run the risk of confusing the higher 1697 * level, as that can be pretty lethal to image consistency. */ 1698 *pcbPreRead = 0; 1699 *pcbPostRead = 0; 1700 1701 out: 1702 LogFlowFunc(("returns %Rrc\n", rc)); 1703 return rc; 1704 } 1705 1706 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1707 static int vhdFlush(void *pBackendData) 1708 { 1709 LogFlowFunc(("pBackendData=%#p", pBackendData)); 1710 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1711 int rc; 1712 1713 rc = vhdFlushImage(pImage); 1714 LogFlowFunc(("returns %Rrc\n", rc)); 1715 return rc; 1716 } 1717 1718 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 1719 static unsigned vhdGetVersion(void *pBackendData) 1720 { 1721 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1722 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1723 unsigned ver = 0; 1724 1725 AssertPtr(pImage); 1726 1727 if (pImage) 1728 ver = 1; /**< @todo use correct version */ 1729 1730 LogFlowFunc(("returns %u\n", ver)); 1731 return ver; 1732 } 1733 1734 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 1735 static uint64_t vhdGetSize(void *pBackendData) 1736 { 1737 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1738 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1739 uint64_t cb = 0; 1740 1741 AssertPtr(pImage); 1742 1743 if (pImage && pImage->pStorage) 1744 cb = pImage->cbSize; 1745 1746 LogFlowFunc(("returns %llu\n", cb)); 1747 return cb; 1748 } 1749 1750 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 1751 static uint64_t vhdGetFileSize(void *pBackendData) 1752 { 1753 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1754 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1755 uint64_t cb = 0; 1756 1757 AssertPtr(pImage); 1758 1759 if (pImage && pImage->pStorage) 1760 cb = pImage->uCurrentEndOfFile + sizeof(VHDFooter); 1761 1762 LogFlowFunc(("returns %lld\n", cb)); 1763 return cb; 1764 } 1765 1766 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 1767 static int vhdGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 1768 { 1769 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 1770 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1771 int rc; 1772 1773 AssertPtr(pImage); 1774 1775 if (pImage) 1776 { 1777 if (pImage->PCHSGeometry.cCylinders) 1778 { 1779 *pPCHSGeometry = pImage->PCHSGeometry; 1780 rc = VINF_SUCCESS; 1781 } 1782 else 1783 rc = VERR_VD_GEOMETRY_NOT_SET; 1784 } 1785 else 1786 rc = VERR_VD_NOT_OPENED; 1787 1788 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors)); 1789 return rc; 1790 } 1791 1792 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 1793 static int vhdSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 1794 { 1795 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1796 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1797 int rc; 1798 1799 AssertPtr(pImage); 1800 1801 if (pImage) 1802 { 1803 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1804 { 1805 rc = VERR_VD_IMAGE_READ_ONLY; 1806 goto out; 1807 } 1808 1809 pImage->PCHSGeometry = *pPCHSGeometry; 1810 rc = VINF_SUCCESS; 1811 } 1812 else 1813 rc = VERR_VD_NOT_OPENED; 1814 1815 out: 1816 LogFlowFunc(("returns %Rrc\n", rc)); 1817 return rc; 1818 } 1819 1820 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 1821 static int vhdGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 1822 { 1823 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 1824 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1825 int rc; 1826 1827 AssertPtr(pImage); 1828 1829 if (pImage) 1830 { 1831 if (pImage->LCHSGeometry.cCylinders) 1832 { 1833 *pLCHSGeometry = pImage->LCHSGeometry; 1834 rc = VINF_SUCCESS; 1835 } 1836 else 1837 rc = VERR_VD_GEOMETRY_NOT_SET; 1838 } 1839 else 1840 rc = VERR_VD_NOT_OPENED; 1841 1842 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors)); 1843 return rc; 1844 } 1845 1846 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 1847 static int vhdSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 1848 { 1849 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1850 int rc; 1851 1852 AssertPtr(pImage); 1853 1854 if (pImage) 1855 { 1856 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1857 { 1858 rc = VERR_VD_IMAGE_READ_ONLY; 1859 goto out; 1860 } 1861 1862 pImage->LCHSGeometry = *pLCHSGeometry; 1863 rc = VINF_SUCCESS; 1864 } 1865 else 1866 rc = VERR_VD_NOT_OPENED; 1867 1868 out: 1869 LogFlowFunc(("returns %Rrc\n", rc)); 1870 return rc; 1871 } 1872 1873 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 1874 static unsigned vhdGetImageFlags(void *pBackendData) 1875 { 1876 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1877 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1878 unsigned uImageFlags; 1879 1880 AssertPtr(pImage); 1881 1882 if (pImage) 1883 uImageFlags = pImage->uImageFlags; 1884 else 1885 uImageFlags = 0; 1886 1887 LogFlowFunc(("returns %#x\n", uImageFlags)); 1888 return uImageFlags; 1889 } 1890 1891 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 1892 static unsigned vhdGetOpenFlags(void *pBackendData) 1893 { 1894 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1895 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1896 unsigned uOpenFlags; 1897 1898 AssertPtr(pImage); 1899 1900 if (pImage) 1901 uOpenFlags = pImage->uOpenFlags; 1902 else 1903 uOpenFlags = 0; 1904 1905 LogFlowFunc(("returns %#x\n", uOpenFlags)); 1906 return uOpenFlags; 1907 } 1908 1909 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 1910 static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 1911 { 1912 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 1913 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1914 int rc; 1915 1916 /* Image must be opened and the new flags must be valid. */ 1917 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 1918 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE 1919 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 1920 { 1921 rc = VERR_INVALID_PARAMETER; 1922 goto out; 1923 } 1924 1925 /* Implement this operation via reopening the image. */ 1926 rc = vhdFreeImage(pImage, false); 1927 if (RT_FAILURE(rc)) 1928 goto out; 1929 rc = vhdOpenImage(pImage, uOpenFlags); 1930 1931 out: 1932 LogFlowFunc(("returns %Rrc\n", rc)); 1933 return rc; 1934 } 1935 1936 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 1937 static int vhdGetComment(void *pBackendData, char *pszComment, 1938 size_t cbComment) 1939 { 1940 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 1941 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1942 int rc; 1943 1944 AssertPtr(pImage); 1945 1946 if (pImage) 1947 rc = VERR_NOT_SUPPORTED; 1948 else 1949 rc = VERR_VD_NOT_OPENED; 1950 1951 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 1952 return rc; 1953 } 1954 1955 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 1956 static int vhdSetComment(void *pBackendData, const char *pszComment) 1957 { 1958 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 1959 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1960 int rc; 1961 1962 AssertPtr(pImage); 1963 1964 if (pImage) 1965 { 1966 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1967 rc = VERR_VD_IMAGE_READ_ONLY; 1968 else 1969 rc = VERR_NOT_SUPPORTED; 1970 } 1971 else 1972 rc = VERR_VD_NOT_OPENED; 1973 1974 LogFlowFunc(("returns %Rrc\n", rc)); 1975 return rc; 1976 } 1977 1978 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 1979 static int vhdGetUuid(void *pBackendData, PRTUUID pUuid) 1980 { 1981 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1982 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1983 int rc; 1984 1985 AssertPtr(pImage); 1986 1987 if (pImage) 1988 { 1989 *pUuid = pImage->ImageUuid; 1990 rc = VINF_SUCCESS; 1991 } 1992 else 1993 rc = VERR_VD_NOT_OPENED; 1994 1995 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 1996 return rc; 1997 } 1998 1999 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 2000 static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid) 2001 { 2002 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2003 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2004 int rc; 2005 2006 AssertPtr(pImage); 2007 2008 if (pImage) 2009 { 2010 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2011 { 2012 pImage->ImageUuid = *pUuid; 2013 /* Update the footer copy. It will get written to disk when the image is closed. */ 2014 memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16); 2015 /* Update checksum. */ 2016 pImage->vhdFooterCopy.Checksum = 0; 2017 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter))); 2018 2019 /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */ 2020 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2021 pImage->fDynHdrNeedsUpdate = true; 2022 rc = VINF_SUCCESS; 2023 } 2024 else 2025 rc = VERR_VD_IMAGE_READ_ONLY; 2026 } 2027 else 2028 rc = VERR_VD_NOT_OPENED; 2029 2030 LogFlowFunc(("returns %Rrc\n", rc)); 2031 return rc; 2032 } 2033 2034 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 2035 static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2036 { 2037 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2038 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2039 int rc; 2040 2041 AssertPtr(pImage); 2042 2043 if (pImage) 2044 rc = VERR_NOT_SUPPORTED; 2045 else 2046 rc = VERR_VD_NOT_OPENED; 2047 2048 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2049 return rc; 2050 } 2051 2052 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 2053 static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2054 { 2055 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2056 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2057 int rc; 2058 2059 AssertPtr(pImage); 2060 2061 if (pImage) 2062 { 2063 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2064 rc = VERR_NOT_SUPPORTED; 2065 else 2066 rc = VERR_VD_IMAGE_READ_ONLY; 2067 } 2068 else 2069 rc = VERR_VD_NOT_OPENED; 2070 2071 LogFlowFunc(("returns %Rrc\n", rc)); 2072 return rc; 2073 } 2074 2075 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 2076 static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid) 2077 { 2078 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2079 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2080 int rc; 2081 2082 AssertPtr(pImage); 2083 2084 if (pImage) 2085 { 2086 *pUuid = pImage->ParentUuid; 2087 rc = VINF_SUCCESS; 2088 } 2089 else 2090 rc = VERR_VD_NOT_OPENED; 2091 2092 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2093 return rc; 2094 } 2095 2096 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 2097 static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2098 { 2099 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2100 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2101 int rc = VINF_SUCCESS; 2102 2103 AssertPtr(pImage); 2104 2105 if (pImage && pImage->pStorage) 2106 { 2107 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2108 { 2109 pImage->ParentUuid = *pUuid; 2110 pImage->fDynHdrNeedsUpdate = true; 2111 } 2112 else 2113 rc = VERR_VD_IMAGE_READ_ONLY; 2114 } 2115 else 2116 rc = VERR_VD_NOT_OPENED; 2117 2118 LogFlowFunc(("returns %Rrc\n", rc)); 2119 return rc; 2120 } 2121 2122 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 2123 static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2124 { 2125 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2126 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2127 int rc; 2128 2129 AssertPtr(pImage); 2130 2131 if (pImage) 2132 rc = VERR_NOT_SUPPORTED; 2133 else 2134 rc = VERR_VD_NOT_OPENED; 2135 2136 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2137 return rc; 2138 } 2139 2140 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 2141 static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2142 { 2143 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2144 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2145 int rc; 2146 2147 AssertPtr(pImage); 2148 2149 if (pImage) 2150 { 2151 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2152 rc = VERR_NOT_SUPPORTED; 2153 else 2154 rc = VERR_VD_IMAGE_READ_ONLY; 2155 } 2156 else 2157 rc = VERR_VD_NOT_OPENED; 2158 2159 LogFlowFunc(("returns %Rrc\n", rc)); 2160 return rc; 2161 } 2162 2163 /** @copydoc VBOXHDDBACKEND::pfnDump */ 2164 static void vhdDump(void *pBackendData) 2165 { 2166 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2167 2168 AssertPtr(pImage); 2169 if (pImage) 2170 { 2171 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%u\n", 2172 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2173 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2174 VHD_SECTOR_SIZE); 2175 vdIfErrorMessage(pImage->pIfError, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 2176 vdIfErrorMessage(pImage->pIfError, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 2177 } 2178 } 2179 2180 /** @copydoc VBOXHDDBACKEND::pfnGetTimestamp */ 2181 static int vhdGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 2182 { 2183 int rc = VINF_SUCCESS; 2184 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2185 2186 AssertPtr(pImage); 2187 2188 if (pImage) 2189 rc = vdIfIoIntFileGetModificationTime(pImage->pIfIo, pImage->pszFilename, pTimeStamp); 2190 else 2191 rc = VERR_VD_NOT_OPENED; 2192 2193 LogFlowFunc(("returns %Rrc\n", rc)); 2194 return rc; 2195 } 2196 2197 /** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */ 2198 static int vhdGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 2199 { 2200 int rc = VINF_SUCCESS; 2201 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2202 2203 AssertPtr(pImage); 2204 2205 if (pImage) 2206 vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp); 2207 else 2208 rc = VERR_VD_NOT_OPENED; 2209 2210 LogFlowFunc(("returns %Rrc\n", rc)); 2211 return rc; 2212 } 2213 2214 /** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */ 2215 static int vhdSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp) 2216 { 2217 int rc = VINF_SUCCESS; 2218 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2219 2220 AssertPtr(pImage); 2221 if (pImage) 2222 { 2223 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2224 rc = VERR_VD_IMAGE_READ_ONLY; 2225 else 2226 { 2227 pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp); 2228 pImage->fDynHdrNeedsUpdate = true; 2229 } 2230 } 2231 else 2232 rc = VERR_VD_NOT_OPENED; 2233 2234 LogFlowFunc(("returns %Rrc\n", rc)); 2235 return rc; 2236 } 2237 2238 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */ 2239 static int vhdGetParentFilename(void *pBackendData, char **ppszParentFilename) 2240 { 2241 int rc = VINF_SUCCESS; 2242 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2243 2244 AssertPtr(pImage); 2245 if (pImage) 2246 *ppszParentFilename = RTStrDup(pImage->pszParentFilename); 2247 else 2248 rc = VERR_VD_NOT_OPENED; 2249 2250 LogFlowFunc(("returns %Rrc\n", rc)); 2251 return rc; 2252 } 2253 2254 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */ 2255 static int vhdSetParentFilename(void *pBackendData, const char *pszParentFilename) 2256 { 2257 int rc = VINF_SUCCESS; 2258 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2259 2260 AssertPtr(pImage); 2261 if (pImage) 2262 { 2263 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2264 rc = VERR_VD_IMAGE_READ_ONLY; 2265 else 2266 { 2267 if (pImage->pszParentFilename) 2268 RTStrFree(pImage->pszParentFilename); 2269 pImage->pszParentFilename = RTStrDup(pszParentFilename); 2270 if (!pImage->pszParentFilename) 2271 rc = VERR_NO_MEMORY; 2272 else 2273 pImage->fDynHdrNeedsUpdate = true; 2274 } 2275 } 2276 else 2277 rc = VERR_VD_NOT_OPENED; 2278 2279 LogFlowFunc(("returns %Rrc\n", rc)); 2280 return rc; 2281 } 2282 2283 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */ 2284 static int vhdAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 2285 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1453 static int vhdRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 1454 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 2286 1455 { 2287 1456 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; … … 2397 1566 } 2398 1567 2399 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 2400 static int vhdAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 2401 PVDIOCTX pIoCtx, 2402 size_t *pcbWriteProcess, size_t *pcbPreRead, 2403 size_t *pcbPostRead, unsigned fWrite) 1568 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1569 static int vhdWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 1570 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 1571 size_t *pcbPostRead, unsigned fWrite) 2404 1572 { 2405 1573 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; … … 2632 1800 } 2633 1801 2634 /** @copydoc VBOXHDDBACKEND::pfn AsyncFlush */2635 static int vhd AsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)1802 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1803 static int vhdFlush(void *pBackendData, PVDIOCTX pIoCtx) 2636 1804 { 2637 1805 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; … … 2639 1807 /* No need to write anything here. Data is always updated on a write. */ 2640 1808 return vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx, NULL, NULL); 1809 } 1810 1811 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 1812 static unsigned vhdGetVersion(void *pBackendData) 1813 { 1814 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1815 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1816 unsigned ver = 0; 1817 1818 AssertPtr(pImage); 1819 1820 if (pImage) 1821 ver = 1; /**< @todo use correct version */ 1822 1823 LogFlowFunc(("returns %u\n", ver)); 1824 return ver; 1825 } 1826 1827 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 1828 static uint64_t vhdGetSize(void *pBackendData) 1829 { 1830 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1831 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1832 uint64_t cb = 0; 1833 1834 AssertPtr(pImage); 1835 1836 if (pImage && pImage->pStorage) 1837 cb = pImage->cbSize; 1838 1839 LogFlowFunc(("returns %llu\n", cb)); 1840 return cb; 1841 } 1842 1843 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 1844 static uint64_t vhdGetFileSize(void *pBackendData) 1845 { 1846 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1847 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1848 uint64_t cb = 0; 1849 1850 AssertPtr(pImage); 1851 1852 if (pImage && pImage->pStorage) 1853 cb = pImage->uCurrentEndOfFile + sizeof(VHDFooter); 1854 1855 LogFlowFunc(("returns %lld\n", cb)); 1856 return cb; 1857 } 1858 1859 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 1860 static int vhdGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 1861 { 1862 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 1863 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1864 int rc; 1865 1866 AssertPtr(pImage); 1867 1868 if (pImage) 1869 { 1870 if (pImage->PCHSGeometry.cCylinders) 1871 { 1872 *pPCHSGeometry = pImage->PCHSGeometry; 1873 rc = VINF_SUCCESS; 1874 } 1875 else 1876 rc = VERR_VD_GEOMETRY_NOT_SET; 1877 } 1878 else 1879 rc = VERR_VD_NOT_OPENED; 1880 1881 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors)); 1882 return rc; 1883 } 1884 1885 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 1886 static int vhdSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 1887 { 1888 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1889 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1890 int rc; 1891 1892 AssertPtr(pImage); 1893 1894 if (pImage) 1895 { 1896 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1897 { 1898 rc = VERR_VD_IMAGE_READ_ONLY; 1899 goto out; 1900 } 1901 1902 pImage->PCHSGeometry = *pPCHSGeometry; 1903 rc = VINF_SUCCESS; 1904 } 1905 else 1906 rc = VERR_VD_NOT_OPENED; 1907 1908 out: 1909 LogFlowFunc(("returns %Rrc\n", rc)); 1910 return rc; 1911 } 1912 1913 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 1914 static int vhdGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 1915 { 1916 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 1917 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1918 int rc; 1919 1920 AssertPtr(pImage); 1921 1922 if (pImage) 1923 { 1924 if (pImage->LCHSGeometry.cCylinders) 1925 { 1926 *pLCHSGeometry = pImage->LCHSGeometry; 1927 rc = VINF_SUCCESS; 1928 } 1929 else 1930 rc = VERR_VD_GEOMETRY_NOT_SET; 1931 } 1932 else 1933 rc = VERR_VD_NOT_OPENED; 1934 1935 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors)); 1936 return rc; 1937 } 1938 1939 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 1940 static int vhdSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 1941 { 1942 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1943 int rc; 1944 1945 AssertPtr(pImage); 1946 1947 if (pImage) 1948 { 1949 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1950 { 1951 rc = VERR_VD_IMAGE_READ_ONLY; 1952 goto out; 1953 } 1954 1955 pImage->LCHSGeometry = *pLCHSGeometry; 1956 rc = VINF_SUCCESS; 1957 } 1958 else 1959 rc = VERR_VD_NOT_OPENED; 1960 1961 out: 1962 LogFlowFunc(("returns %Rrc\n", rc)); 1963 return rc; 1964 } 1965 1966 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 1967 static unsigned vhdGetImageFlags(void *pBackendData) 1968 { 1969 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1970 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1971 unsigned uImageFlags; 1972 1973 AssertPtr(pImage); 1974 1975 if (pImage) 1976 uImageFlags = pImage->uImageFlags; 1977 else 1978 uImageFlags = 0; 1979 1980 LogFlowFunc(("returns %#x\n", uImageFlags)); 1981 return uImageFlags; 1982 } 1983 1984 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 1985 static unsigned vhdGetOpenFlags(void *pBackendData) 1986 { 1987 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1988 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1989 unsigned uOpenFlags; 1990 1991 AssertPtr(pImage); 1992 1993 if (pImage) 1994 uOpenFlags = pImage->uOpenFlags; 1995 else 1996 uOpenFlags = 0; 1997 1998 LogFlowFunc(("returns %#x\n", uOpenFlags)); 1999 return uOpenFlags; 2000 } 2001 2002 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 2003 static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 2004 { 2005 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2006 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2007 int rc; 2008 2009 /* Image must be opened and the new flags must be valid. */ 2010 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 2011 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE 2012 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 2013 { 2014 rc = VERR_INVALID_PARAMETER; 2015 goto out; 2016 } 2017 2018 /* Implement this operation via reopening the image. */ 2019 rc = vhdFreeImage(pImage, false); 2020 if (RT_FAILURE(rc)) 2021 goto out; 2022 rc = vhdOpenImage(pImage, uOpenFlags); 2023 2024 out: 2025 LogFlowFunc(("returns %Rrc\n", rc)); 2026 return rc; 2027 } 2028 2029 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 2030 static int vhdGetComment(void *pBackendData, char *pszComment, 2031 size_t cbComment) 2032 { 2033 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2034 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2035 int rc; 2036 2037 AssertPtr(pImage); 2038 2039 if (pImage) 2040 rc = VERR_NOT_SUPPORTED; 2041 else 2042 rc = VERR_VD_NOT_OPENED; 2043 2044 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 2045 return rc; 2046 } 2047 2048 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 2049 static int vhdSetComment(void *pBackendData, const char *pszComment) 2050 { 2051 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2052 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2053 int rc; 2054 2055 AssertPtr(pImage); 2056 2057 if (pImage) 2058 { 2059 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2060 rc = VERR_VD_IMAGE_READ_ONLY; 2061 else 2062 rc = VERR_NOT_SUPPORTED; 2063 } 2064 else 2065 rc = VERR_VD_NOT_OPENED; 2066 2067 LogFlowFunc(("returns %Rrc\n", rc)); 2068 return rc; 2069 } 2070 2071 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 2072 static int vhdGetUuid(void *pBackendData, PRTUUID pUuid) 2073 { 2074 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2075 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2076 int rc; 2077 2078 AssertPtr(pImage); 2079 2080 if (pImage) 2081 { 2082 *pUuid = pImage->ImageUuid; 2083 rc = VINF_SUCCESS; 2084 } 2085 else 2086 rc = VERR_VD_NOT_OPENED; 2087 2088 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2089 return rc; 2090 } 2091 2092 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 2093 static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid) 2094 { 2095 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2096 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2097 int rc; 2098 2099 AssertPtr(pImage); 2100 2101 if (pImage) 2102 { 2103 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2104 { 2105 pImage->ImageUuid = *pUuid; 2106 /* Update the footer copy. It will get written to disk when the image is closed. */ 2107 memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16); 2108 /* Update checksum. */ 2109 pImage->vhdFooterCopy.Checksum = 0; 2110 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter))); 2111 2112 /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */ 2113 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2114 pImage->fDynHdrNeedsUpdate = true; 2115 rc = VINF_SUCCESS; 2116 } 2117 else 2118 rc = VERR_VD_IMAGE_READ_ONLY; 2119 } 2120 else 2121 rc = VERR_VD_NOT_OPENED; 2122 2123 LogFlowFunc(("returns %Rrc\n", rc)); 2124 return rc; 2125 } 2126 2127 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 2128 static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2129 { 2130 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2131 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2132 int rc; 2133 2134 AssertPtr(pImage); 2135 2136 if (pImage) 2137 rc = VERR_NOT_SUPPORTED; 2138 else 2139 rc = VERR_VD_NOT_OPENED; 2140 2141 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2142 return rc; 2143 } 2144 2145 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 2146 static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2147 { 2148 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2149 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2150 int rc; 2151 2152 AssertPtr(pImage); 2153 2154 if (pImage) 2155 { 2156 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2157 rc = VERR_NOT_SUPPORTED; 2158 else 2159 rc = VERR_VD_IMAGE_READ_ONLY; 2160 } 2161 else 2162 rc = VERR_VD_NOT_OPENED; 2163 2164 LogFlowFunc(("returns %Rrc\n", rc)); 2165 return rc; 2166 } 2167 2168 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 2169 static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid) 2170 { 2171 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2172 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2173 int rc; 2174 2175 AssertPtr(pImage); 2176 2177 if (pImage) 2178 { 2179 *pUuid = pImage->ParentUuid; 2180 rc = VINF_SUCCESS; 2181 } 2182 else 2183 rc = VERR_VD_NOT_OPENED; 2184 2185 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2186 return rc; 2187 } 2188 2189 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 2190 static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2191 { 2192 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2193 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2194 int rc = VINF_SUCCESS; 2195 2196 AssertPtr(pImage); 2197 2198 if (pImage && pImage->pStorage) 2199 { 2200 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2201 { 2202 pImage->ParentUuid = *pUuid; 2203 pImage->fDynHdrNeedsUpdate = true; 2204 } 2205 else 2206 rc = VERR_VD_IMAGE_READ_ONLY; 2207 } 2208 else 2209 rc = VERR_VD_NOT_OPENED; 2210 2211 LogFlowFunc(("returns %Rrc\n", rc)); 2212 return rc; 2213 } 2214 2215 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 2216 static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2217 { 2218 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2219 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2220 int rc; 2221 2222 AssertPtr(pImage); 2223 2224 if (pImage) 2225 rc = VERR_NOT_SUPPORTED; 2226 else 2227 rc = VERR_VD_NOT_OPENED; 2228 2229 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2230 return rc; 2231 } 2232 2233 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 2234 static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2235 { 2236 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2237 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2238 int rc; 2239 2240 AssertPtr(pImage); 2241 2242 if (pImage) 2243 { 2244 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2245 rc = VERR_NOT_SUPPORTED; 2246 else 2247 rc = VERR_VD_IMAGE_READ_ONLY; 2248 } 2249 else 2250 rc = VERR_VD_NOT_OPENED; 2251 2252 LogFlowFunc(("returns %Rrc\n", rc)); 2253 return rc; 2254 } 2255 2256 /** @copydoc VBOXHDDBACKEND::pfnDump */ 2257 static void vhdDump(void *pBackendData) 2258 { 2259 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2260 2261 AssertPtr(pImage); 2262 if (pImage) 2263 { 2264 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%u\n", 2265 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2266 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2267 VHD_SECTOR_SIZE); 2268 vdIfErrorMessage(pImage->pIfError, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 2269 vdIfErrorMessage(pImage->pIfError, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 2270 } 2271 } 2272 2273 /** @copydoc VBOXHDDBACKEND::pfnGetTimestamp */ 2274 static int vhdGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 2275 { 2276 int rc = VINF_SUCCESS; 2277 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2278 2279 AssertPtr(pImage); 2280 2281 if (pImage) 2282 rc = vdIfIoIntFileGetModificationTime(pImage->pIfIo, pImage->pszFilename, pTimeStamp); 2283 else 2284 rc = VERR_VD_NOT_OPENED; 2285 2286 LogFlowFunc(("returns %Rrc\n", rc)); 2287 return rc; 2288 } 2289 2290 /** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */ 2291 static int vhdGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 2292 { 2293 int rc = VINF_SUCCESS; 2294 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2295 2296 AssertPtr(pImage); 2297 2298 if (pImage) 2299 vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp); 2300 else 2301 rc = VERR_VD_NOT_OPENED; 2302 2303 LogFlowFunc(("returns %Rrc\n", rc)); 2304 return rc; 2305 } 2306 2307 /** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */ 2308 static int vhdSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp) 2309 { 2310 int rc = VINF_SUCCESS; 2311 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2312 2313 AssertPtr(pImage); 2314 if (pImage) 2315 { 2316 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2317 rc = VERR_VD_IMAGE_READ_ONLY; 2318 else 2319 { 2320 pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp); 2321 pImage->fDynHdrNeedsUpdate = true; 2322 } 2323 } 2324 else 2325 rc = VERR_VD_NOT_OPENED; 2326 2327 LogFlowFunc(("returns %Rrc\n", rc)); 2328 return rc; 2329 } 2330 2331 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */ 2332 static int vhdGetParentFilename(void *pBackendData, char **ppszParentFilename) 2333 { 2334 int rc = VINF_SUCCESS; 2335 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2336 2337 AssertPtr(pImage); 2338 if (pImage) 2339 *ppszParentFilename = RTStrDup(pImage->pszParentFilename); 2340 else 2341 rc = VERR_VD_NOT_OPENED; 2342 2343 LogFlowFunc(("returns %Rrc\n", rc)); 2344 return rc; 2345 } 2346 2347 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */ 2348 static int vhdSetParentFilename(void *pBackendData, const char *pszParentFilename) 2349 { 2350 int rc = VINF_SUCCESS; 2351 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2352 2353 AssertPtr(pImage); 2354 if (pImage) 2355 { 2356 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2357 rc = VERR_VD_IMAGE_READ_ONLY; 2358 else 2359 { 2360 if (pImage->pszParentFilename) 2361 RTStrFree(pImage->pszParentFilename); 2362 pImage->pszParentFilename = RTStrDup(pszParentFilename); 2363 if (!pImage->pszParentFilename) 2364 rc = VERR_NO_MEMORY; 2365 else 2366 pImage->fDynHdrNeedsUpdate = true; 2367 } 2368 } 2369 else 2370 rc = VERR_VD_NOT_OPENED; 2371 2372 LogFlowFunc(("returns %Rrc\n", rc)); 2373 return rc; 2641 2374 } 2642 2375 … … 3056 2789 /* Update header information in base image file. */ 3057 2790 pImage->fDynHdrNeedsUpdate = true; 3058 vhdFlush (pImage);2791 vhdFlushImage(pImage); 3059 2792 } 3060 2793 /* Same size doesn't change the image at all. */ … … 3438 3171 /* pfnFlush */ 3439 3172 vhdFlush, 3173 /* pfnDiscard */ 3174 NULL, 3440 3175 /* pfnGetVersion */ 3441 3176 vhdGetVersion, … … 3490 3225 /* pfnSetParentFilename */ 3491 3226 vhdSetParentFilename, 3492 /* pfnAsyncRead */3493 vhdAsyncRead,3494 /* pfnAsyncWrite */3495 vhdAsyncWrite,3496 /* pfnAsyncFlush */3497 vhdAsyncFlush,3498 3227 /* pfnComposeLocation */ 3499 3228 genericFileComposeLocation, … … 3504 3233 /* pfnResize */ 3505 3234 vhdResize, 3506 /* pfnDiscard */3507 NULL,3508 /* pfnAsyncDiscard */3509 NULL,3510 3235 /* pfnRepair */ 3511 3236 vhdRepair -
trunk/src/VBox/Storage/VHDX.cpp
r44233 r44252 1864 1864 1865 1865 /** @copydoc VBOXHDDBACKEND::pfnRead */ 1866 static int vhdxRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 1867 size_t cbToRead, size_t *pcbActuallyRead) 1868 { 1869 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 1866 static int vhdxRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 1867 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1868 { 1869 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1870 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 1870 1871 PVHDXIMAGE pImage = (PVHDXIMAGE)pBackendData; 1871 1872 int rc = VINF_SUCCESS; … … 1896 1897 case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_UNMAPPED: 1897 1898 { 1898 memset(pvBuf, 0, cbToRead);1899 vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); 1899 1900 break; 1900 1901 } … … 1902 1903 { 1903 1904 uint64_t offFile = VHDX_BAT_ENTRY_GET_FILE_OFFSET(uBatEntry) + offRead; 1904 rc = vdIfIoIntFileRead Sync(pImage->pIfIo, pImage->pStorage, offFile,1905 p vBuf, cbToRead);1905 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile, 1906 pIoCtx, cbToRead); 1906 1907 break; 1907 1908 } … … 1921 1922 1922 1923 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1923 static int vhdxWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,1924 size_t cbToWrite, size_t *pcbWriteProcess,1925 size_t *pcbPreRead,size_t *pcbPostRead, unsigned fWrite)1926 { 1927 LogFlowFunc(("pBackendData=%#p uOffset=%llu p vBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",1928 pBackendData, uOffset, p vBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));1924 static int vhdxWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 1925 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 1926 size_t *pcbPostRead, unsigned fWrite) 1927 { 1928 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 1929 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 1929 1930 PVHDXIMAGE pImage = (PVHDXIMAGE)pBackendData; 1930 1931 int rc; … … 1947 1948 1948 1949 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1949 static int vhdxFlush(void *pBackendData )1950 { 1951 LogFlowFunc(("pBackendData=%#p \n", pBackendData));1950 static int vhdxFlush(void *pBackendData, PVDIOCTX pIoCtx) 1951 { 1952 LogFlowFunc(("pBackendData=%#p pIoCtx=%#p\n", pBackendData, pIoCtx)); 1952 1953 PVHDXIMAGE pImage = (PVHDXIMAGE)pBackendData; 1953 1954 int rc; … … 2427 2428 /* pfnFlush */ 2428 2429 vhdxFlush, 2430 /* pfnDiscard */ 2431 NULL, 2429 2432 /* pfnGetVersion */ 2430 2433 vhdxGetVersion, … … 2479 2482 /* pfnSetParentFilename */ 2480 2483 NULL, 2481 /* pfnAsyncRead */2482 NULL,2483 /* pfnAsyncWrite */2484 NULL,2485 /* pfnAsyncFlush */2486 NULL,2487 2484 /* pfnComposeLocation */ 2488 2485 genericFileComposeLocation, … … 2493 2490 /* pfnResize */ 2494 2491 NULL, 2495 /* pfnDiscard */2496 NULL,2497 /* pfnAsyncDiscard */2498 NULL,2499 2492 /* pfnRepair */ 2500 2493 NULL -
trunk/src/VBox/Storage/VMDK.cpp
r44233 r44252 233 233 /** File open flags for consistency checking. */ 234 234 unsigned fOpen; 235 /** Flag whether this file has been opened for async I/O. */236 bool fAsyncIO;237 235 /** Handle for sync/async file abstraction.*/ 238 236 PVDIOSTORAGE pStorage; … … 530 528 531 529 static int vmdkCreateExtents(PVMDKIMAGE pImage, unsigned cExtents); 532 static int vmdkFlushImage(PVMDKIMAGE pImage );530 static int vmdkFlushImage(PVMDKIMAGE pImage, PVDIOCTX pIoCtx); 533 531 static int vmdkSetImageComment(PVMDKIMAGE pImage, const char *pszComment); 534 532 static int vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete); 535 533 536 static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq); 534 static int vmdkAllocGrainComplete(void *pBackendData, PVDIOCTX pIoCtx, 535 void *pvUser, int rcReq); 537 536 538 537 /** … … 541 540 */ 542 541 static int vmdkFileOpen(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile, 543 const char *pszFilename, uint32_t fOpen , bool fAsyncIO)542 const char *pszFilename, uint32_t fOpen) 544 543 { 545 544 int rc = VINF_SUCCESS; … … 577 576 } 578 577 pVmdkFile->fOpen = fOpen; 579 pVmdkFile->fAsyncIO = fAsyncIO;580 578 581 579 rc = vdIfIoIntFileOpen(pImage->pIfIo, pszFilename, fOpen, … … 680 678 uint64_t *puLBA, uint32_t *pcbMarkerData) 681 679 { 682 if (pExtent->pFile->fAsyncIO) 683 { 684 AssertMsgFailed(("TODO\n")); 685 return VERR_NOT_SUPPORTED; 686 } 687 else 688 { 689 int rc; 690 PRTZIPDECOMP pZip = NULL; 691 VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain; 692 size_t cbCompSize, cbActuallyRead; 693 694 if (!pcvMarker) 695 { 696 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage, 697 uOffset, pMarker, RT_OFFSETOF(VMDKMARKER, uType)); 698 if (RT_FAILURE(rc)) 699 return rc; 700 } 701 else 702 { 703 memcpy(pMarker, pcvMarker, RT_OFFSETOF(VMDKMARKER, uType)); 704 /* pcvMarker endianness has already been partially transformed, fix it */ 705 pMarker->uSector = RT_H2LE_U64(pMarker->uSector); 706 pMarker->cbSize = RT_H2LE_U32(pMarker->cbSize); 707 } 708 709 cbCompSize = RT_LE2H_U32(pMarker->cbSize); 710 if (cbCompSize == 0) 711 { 712 AssertMsgFailed(("VMDK: corrupted marker\n")); 713 return VERR_VD_VMDK_INVALID_FORMAT; 714 } 715 716 /* Sanity check - the expansion ratio should be much less than 2. */ 717 Assert(cbCompSize < 2 * cbToRead); 718 if (cbCompSize >= 2 * cbToRead) 719 return VERR_VD_VMDK_INVALID_FORMAT; 720 721 /* Compressed grain marker. Data follows immediately. */ 680 int rc; 681 PRTZIPDECOMP pZip = NULL; 682 VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain; 683 size_t cbCompSize, cbActuallyRead; 684 685 if (!pcvMarker) 686 { 722 687 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage, 723 uOffset + RT_OFFSETOF(VMDKMARKER, uType), 724 (uint8_t *)pExtent->pvCompGrain 725 + RT_OFFSETOF(VMDKMARKER, uType), 726 RT_ALIGN_Z( cbCompSize 727 + RT_OFFSETOF(VMDKMARKER, uType), 728 512) 729 - RT_OFFSETOF(VMDKMARKER, uType)); 730 731 if (puLBA) 732 *puLBA = RT_LE2H_U64(pMarker->uSector); 733 if (pcbMarkerData) 734 *pcbMarkerData = RT_ALIGN( cbCompSize 735 + RT_OFFSETOF(VMDKMARKER, uType), 736 512); 737 738 VMDKCOMPRESSIO InflateState; 739 InflateState.pImage = pImage; 740 InflateState.iOffset = -1; 741 InflateState.cbCompGrain = cbCompSize + RT_OFFSETOF(VMDKMARKER, uType); 742 InflateState.pvCompGrain = pExtent->pvCompGrain; 743 744 rc = RTZipDecompCreate(&pZip, &InflateState, vmdkFileInflateHelper); 688 uOffset, pMarker, RT_OFFSETOF(VMDKMARKER, uType)); 745 689 if (RT_FAILURE(rc)) 746 690 return rc; 747 rc = RTZipDecompress(pZip, pvBuf, cbToRead, &cbActuallyRead); 748 RTZipDecompDestroy(pZip); 749 if (RT_FAILURE(rc)) 750 { 751 if (rc == VERR_ZIP_CORRUPTED) 752 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: Compressed image is corrupted '%s'"), pExtent->pszFullname); 753 return rc; 754 } 755 if (cbActuallyRead != cbToRead) 756 rc = VERR_VD_VMDK_INVALID_FORMAT; 691 } 692 else 693 { 694 memcpy(pMarker, pcvMarker, RT_OFFSETOF(VMDKMARKER, uType)); 695 /* pcvMarker endianness has already been partially transformed, fix it */ 696 pMarker->uSector = RT_H2LE_U64(pMarker->uSector); 697 pMarker->cbSize = RT_H2LE_U32(pMarker->cbSize); 698 } 699 700 cbCompSize = RT_LE2H_U32(pMarker->cbSize); 701 if (cbCompSize == 0) 702 { 703 AssertMsgFailed(("VMDK: corrupted marker\n")); 704 return VERR_VD_VMDK_INVALID_FORMAT; 705 } 706 707 /* Sanity check - the expansion ratio should be much less than 2. */ 708 Assert(cbCompSize < 2 * cbToRead); 709 if (cbCompSize >= 2 * cbToRead) 710 return VERR_VD_VMDK_INVALID_FORMAT; 711 712 /* Compressed grain marker. Data follows immediately. */ 713 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage, 714 uOffset + RT_OFFSETOF(VMDKMARKER, uType), 715 (uint8_t *)pExtent->pvCompGrain 716 + RT_OFFSETOF(VMDKMARKER, uType), 717 RT_ALIGN_Z( cbCompSize 718 + RT_OFFSETOF(VMDKMARKER, uType), 719 512) 720 - RT_OFFSETOF(VMDKMARKER, uType)); 721 722 if (puLBA) 723 *puLBA = RT_LE2H_U64(pMarker->uSector); 724 if (pcbMarkerData) 725 *pcbMarkerData = RT_ALIGN( cbCompSize 726 + RT_OFFSETOF(VMDKMARKER, uType), 727 512); 728 729 VMDKCOMPRESSIO InflateState; 730 InflateState.pImage = pImage; 731 InflateState.iOffset = -1; 732 InflateState.cbCompGrain = cbCompSize + RT_OFFSETOF(VMDKMARKER, uType); 733 InflateState.pvCompGrain = pExtent->pvCompGrain; 734 735 rc = RTZipDecompCreate(&pZip, &InflateState, vmdkFileInflateHelper); 736 if (RT_FAILURE(rc)) 757 737 return rc; 758 } 738 rc = RTZipDecompress(pZip, pvBuf, cbToRead, &cbActuallyRead); 739 RTZipDecompDestroy(pZip); 740 if (RT_FAILURE(rc)) 741 { 742 if (rc == VERR_ZIP_CORRUPTED) 743 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: Compressed image is corrupted '%s'"), pExtent->pszFullname); 744 return rc; 745 } 746 if (cbActuallyRead != cbToRead) 747 rc = VERR_VD_VMDK_INVALID_FORMAT; 748 return rc; 759 749 } 760 750 … … 789 779 uint32_t *pcbMarkerData) 790 780 { 791 if (pExtent->pFile->fAsyncIO) 792 { 793 AssertMsgFailed(("TODO\n")); 794 return VERR_NOT_SUPPORTED; 795 } 796 else 797 { 798 int rc; 799 PRTZIPCOMP pZip = NULL; 800 VMDKCOMPRESSIO DeflateState; 801 802 DeflateState.pImage = pImage; 803 DeflateState.iOffset = -1; 804 DeflateState.cbCompGrain = pExtent->cbCompGrain; 805 DeflateState.pvCompGrain = pExtent->pvCompGrain; 806 807 rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper, 808 RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT); 781 int rc; 782 PRTZIPCOMP pZip = NULL; 783 VMDKCOMPRESSIO DeflateState; 784 785 DeflateState.pImage = pImage; 786 DeflateState.iOffset = -1; 787 DeflateState.cbCompGrain = pExtent->cbCompGrain; 788 DeflateState.pvCompGrain = pExtent->pvCompGrain; 789 790 rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper, 791 RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT); 792 if (RT_FAILURE(rc)) 793 return rc; 794 rc = RTZipCompress(pZip, pvBuf, cbToWrite); 795 if (RT_SUCCESS(rc)) 796 rc = RTZipCompFinish(pZip); 797 RTZipCompDestroy(pZip); 798 if (RT_SUCCESS(rc)) 799 { 800 Assert( DeflateState.iOffset > 0 801 && (size_t)DeflateState.iOffset <= DeflateState.cbCompGrain); 802 803 /* pad with zeroes to get to a full sector size */ 804 uint32_t uSize = DeflateState.iOffset; 805 if (uSize % 512) 806 { 807 uint32_t uSizeAlign = RT_ALIGN(uSize, 512); 808 memset((uint8_t *)pExtent->pvCompGrain + uSize, '\0', 809 uSizeAlign - uSize); 810 uSize = uSizeAlign; 811 } 812 813 if (pcbMarkerData) 814 *pcbMarkerData = uSize; 815 816 /* Compressed grain marker. Data follows immediately. */ 817 VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain; 818 pMarker->uSector = RT_H2LE_U64(uLBA); 819 pMarker->cbSize = RT_H2LE_U32( DeflateState.iOffset 820 - RT_OFFSETOF(VMDKMARKER, uType)); 821 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage, 822 uOffset, pMarker, uSize); 809 823 if (RT_FAILURE(rc)) 810 824 return rc; 811 rc = RTZipCompress(pZip, pvBuf, cbToWrite); 812 if (RT_SUCCESS(rc)) 813 rc = RTZipCompFinish(pZip); 814 RTZipCompDestroy(pZip); 815 if (RT_SUCCESS(rc)) 816 { 817 Assert( DeflateState.iOffset > 0 818 && (size_t)DeflateState.iOffset <= DeflateState.cbCompGrain); 819 820 /* pad with zeroes to get to a full sector size */ 821 uint32_t uSize = DeflateState.iOffset; 822 if (uSize % 512) 823 { 824 uint32_t uSizeAlign = RT_ALIGN(uSize, 512); 825 memset((uint8_t *)pExtent->pvCompGrain + uSize, '\0', 826 uSizeAlign - uSize); 827 uSize = uSizeAlign; 828 } 829 830 if (pcbMarkerData) 831 *pcbMarkerData = uSize; 832 833 /* Compressed grain marker. Data follows immediately. */ 834 VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain; 835 pMarker->uSector = RT_H2LE_U64(uLBA); 836 pMarker->cbSize = RT_H2LE_U32( DeflateState.iOffset 837 - RT_OFFSETOF(VMDKMARKER, uType)); 838 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage, 839 uOffset, pMarker, uSize); 840 if (RT_FAILURE(rc)) 841 return rc; 842 } 843 return rc; 844 } 825 } 826 return rc; 845 827 } 846 828 … … 2430 2412 * Internal: write/update the descriptor part of the image. 2431 2413 */ 2432 static int vmdkWriteDescriptor(PVMDKIMAGE pImage )2414 static int vmdkWriteDescriptor(PVMDKIMAGE pImage, PVDIOCTX pIoCtx) 2433 2415 { 2434 2416 int rc = VINF_SUCCESS; … … 2436 2418 uint64_t uOffset; 2437 2419 PVMDKFILE pDescFile; 2438 void *pvDescriptor; 2439 size_t cbDescriptor; 2440 2441 if (pImage->pDescData) 2442 { 2443 /* Separate descriptor file. */ 2444 uOffset = 0; 2445 cbLimit = 0; 2446 pDescFile = pImage->pFile; 2447 } 2448 else 2449 { 2450 /* Embedded descriptor file. */ 2451 uOffset = VMDK_SECTOR2BYTE(pImage->pExtents[0].uDescriptorSector); 2452 cbLimit = VMDK_SECTOR2BYTE(pImage->pExtents[0].cDescriptorSectors); 2453 pDescFile = pImage->pExtents[0].pFile; 2454 } 2455 /* Bail out if there is no file to write to. */ 2456 if (pDescFile == NULL) 2457 return VERR_INVALID_PARAMETER; 2458 2459 rc = vmdkDescriptorPrepare(pImage, cbLimit, &pvDescriptor, &cbDescriptor); 2460 if (RT_SUCCESS(rc)) 2461 { 2462 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pDescFile->pStorage, uOffset, 2463 pvDescriptor, cbLimit ? cbLimit : cbDescriptor); 2464 if (RT_FAILURE(rc)) 2465 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); 2466 2467 if (RT_SUCCESS(rc) && !cbLimit) 2468 { 2469 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pDescFile->pStorage, cbDescriptor); 2470 if (RT_FAILURE(rc)) 2471 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename); 2472 } 2473 2474 if (RT_SUCCESS(rc)) 2475 pImage->Descriptor.fDirty = false; 2476 2477 RTMemFree(pvDescriptor); 2478 } 2479 2480 return rc; 2481 } 2482 2483 /** 2484 * Internal: write/update the descriptor part of the image - async version. 2485 */ 2486 static int vmdkWriteDescriptorAsync(PVMDKIMAGE pImage, PVDIOCTX pIoCtx) 2487 { 2488 int rc = VINF_SUCCESS; 2489 uint64_t cbLimit; 2490 uint64_t uOffset; 2491 PVMDKFILE pDescFile; 2492 void *pvDescriptor; 2420 void *pvDescriptor = NULL; 2493 2421 size_t cbDescriptor; 2494 2422 … … 2533 2461 pImage->Descriptor.fDirty = false; 2534 2462 2535 RTMemFree(pvDescriptor); 2463 if (pvDescriptor) 2464 RTMemFree(pvDescriptor); 2536 2465 return rc; 2537 2466 … … 2781 2710 */ 2782 2711 static int vmdkWriteMetaSparseExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 2783 uint64_t uOffset )2712 uint64_t uOffset, PVDIOCTX pIoCtx) 2784 2713 { 2785 2714 SparseExtentHeader Header; … … 2832 2761 Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression); 2833 2762 2834 int rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,2835 uOffset, &Header, sizeof(Header));2836 AssertRC(rc);2837 if (RT_FAILURE(rc))2838 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);2839 return rc;2840 }2841 2842 /**2843 * Internal: write/update the metadata for a sparse extent - async version.2844 */2845 static int vmdkWriteMetaSparseExtentAsync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,2846 uint64_t uOffset, PVDIOCTX pIoCtx)2847 {2848 SparseExtentHeader Header;2849 2850 memset(&Header, '\0', sizeof(Header));2851 Header.magicNumber = RT_H2LE_U32(VMDK_SPARSE_MAGICNUMBER);2852 Header.version = RT_H2LE_U32(pExtent->uVersion);2853 Header.flags = RT_H2LE_U32(RT_BIT(0));2854 if (pExtent->pRGD)2855 Header.flags |= RT_H2LE_U32(RT_BIT(1));2856 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)2857 Header.flags |= RT_H2LE_U32(RT_BIT(16) | RT_BIT(17));2858 Header.capacity = RT_H2LE_U64(pExtent->cSectors);2859 Header.grainSize = RT_H2LE_U64(pExtent->cSectorsPerGrain);2860 Header.descriptorOffset = RT_H2LE_U64(pExtent->uDescriptorSector);2861 Header.descriptorSize = RT_H2LE_U64(pExtent->cDescriptorSectors);2862 Header.numGTEsPerGT = RT_H2LE_U32(pExtent->cGTEntries);2863 if (pExtent->fFooter && uOffset == 0)2864 {2865 if (pExtent->pRGD)2866 {2867 Assert(pExtent->uSectorRGD);2868 Header.rgdOffset = RT_H2LE_U64(VMDK_GD_AT_END);2869 Header.gdOffset = RT_H2LE_U64(VMDK_GD_AT_END);2870 }2871 else2872 {2873 Header.gdOffset = RT_H2LE_U64(VMDK_GD_AT_END);2874 }2875 }2876 else2877 {2878 if (pExtent->pRGD)2879 {2880 Assert(pExtent->uSectorRGD);2881 Header.rgdOffset = RT_H2LE_U64(pExtent->uSectorRGD);2882 Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD);2883 }2884 else2885 {2886 Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD);2887 }2888 }2889 Header.overHead = RT_H2LE_U64(pExtent->cOverheadSectors);2890 Header.uncleanShutdown = pExtent->fUncleanShutdown;2891 Header.singleEndLineChar = '\n';2892 Header.nonEndLineChar = ' ';2893 Header.doubleEndLineChar1 = '\r';2894 Header.doubleEndLineChar2 = '\n';2895 Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);2896 2897 2763 int rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pExtent->pFile->pStorage, 2898 2764 uOffset, &Header, sizeof(Header), … … 3116 2982 3117 2983 rc = vmdkFileOpen(pImage, &pFile, pImage->pszFilename, 3118 VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */), 3119 false /* fAsyncIO */); 2984 VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */)); 3120 2985 if (RT_FAILURE(rc)) 3121 2986 { … … 3357 3222 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3358 3223 VDOpenFlagsToFileOpenFlags(uOpenFlags, 3359 false /* fCreate */), 3360 false /* fAsyncIO */); 3224 false /* fCreate */)); 3361 3225 if (RT_FAILURE(rc)) 3362 3226 { … … 3385 3249 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3386 3250 VDOpenFlagsToFileOpenFlags(uOpenFlags, 3387 false /* fCreate */), 3388 true /* fAsyncIO */); 3251 false /* fCreate */)); 3389 3252 if (RT_FAILURE(rc)) 3390 3253 { … … 3423 3286 3424 3287 /* Update the image metadata now in case has changed. */ 3425 rc = vmdkFlushImage(pImage );3288 rc = vmdkFlushImage(pImage, NULL); 3426 3289 if (RT_FAILURE(rc)) 3427 3290 goto out; … … 3488 3351 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 3489 3352 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3490 true /* fCreate */), 3491 false /* fAsyncIO */); 3353 true /* fCreate */)); 3492 3354 if (RT_FAILURE(rc)) 3493 3355 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 3513 3375 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3514 3376 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 3515 false /* fCreate */), 3516 false /* fAsyncIO */); 3377 false /* fCreate */)); 3517 3378 if (RT_FAILURE(rc)) 3518 3379 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname); … … 3551 3412 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 3552 3413 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3553 true /* fCreate */), 3554 false /* fAsyncIO */); 3414 true /* fCreate */)); 3555 3415 if (RT_FAILURE(rc)) 3556 3416 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 3623 3483 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3624 3484 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3625 true /* fCreate */), 3626 false /* fAsyncIO */); 3485 true /* fCreate */)); 3627 3486 if (RT_FAILURE(rc)) 3628 3487 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname); … … 3659 3518 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3660 3519 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 3661 false /* fCreate */), 3662 false /* fAsyncIO */); 3520 false /* fCreate */)); 3663 3521 if (RT_FAILURE(rc)) 3664 3522 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname); … … 3733 3591 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 3734 3592 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3735 true /* fCreate */), 3736 false /* fAsyncIO */); 3593 true /* fCreate */)); 3737 3594 if (RT_FAILURE(rc)) 3738 3595 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename); … … 3804 3661 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3805 3662 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3806 true /* fCreate */), 3807 false /* fAsyncIO */); 3663 true /* fCreate */)); 3808 3664 if (RT_FAILURE(rc)) 3809 3665 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname); … … 4003 3859 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 4004 3860 true /* fCreate */) 4005 & ~RTFILE_O_READ, 4006 false /* fAsyncIO */); 3861 & ~RTFILE_O_READ); 4007 3862 if (RT_FAILURE(rc)) 4008 3863 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname); … … 4209 4064 pImage->pExtents[0].cDescriptorSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64( pImage->Descriptor.aLines[pImage->Descriptor.cLines] 4210 4065 - pImage->Descriptor.aLines[0], 512)); 4211 rc = vmdkWriteMetaSparseExtent(pImage, &pImage->pExtents[0], 0 );4066 rc = vmdkWriteMetaSparseExtent(pImage, &pImage->pExtents[0], 0, NULL); 4212 4067 if (RT_FAILURE(rc)) 4213 4068 { … … 4216 4071 } 4217 4072 4218 rc = vmdkWriteDescriptor(pImage );4073 rc = vmdkWriteDescriptor(pImage, NULL); 4219 4074 if (RT_FAILURE(rc)) 4220 4075 { … … 4224 4079 } 4225 4080 else 4226 rc = vmdkFlushImage(pImage );4081 rc = vmdkFlushImage(pImage, NULL); 4227 4082 4228 4083 out: … … 4449 4304 4450 4305 uFileOffset += 512; 4451 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, uFileOffset );4306 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, uFileOffset, NULL); 4452 4307 AssertRC(rc); 4453 4308 … … 4461 4316 } 4462 4317 else 4463 vmdkFlushImage(pImage );4318 vmdkFlushImage(pImage, NULL); 4464 4319 4465 4320 if (pImage->pExtents != NULL) … … 4494 4349 * Internal. Flush image data (and metadata) to disk. 4495 4350 */ 4496 static int vmdkFlushImage(PVMDKIMAGE pImage )4351 static int vmdkFlushImage(PVMDKIMAGE pImage, PVDIOCTX pIoCtx) 4497 4352 { 4498 4353 PVMDKEXTENT pExtent; … … 4502 4357 if (pImage->Descriptor.fDirty) 4503 4358 { 4504 rc = vmdkWriteDescriptor(pImage );4359 rc = vmdkWriteDescriptor(pImage, pIoCtx); 4505 4360 if (RT_FAILURE(rc)) 4506 4361 goto out; … … 4517 4372 if (!pExtent->fFooter) 4518 4373 { 4519 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, 0 );4374 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, 0, pIoCtx); 4520 4375 if (RT_FAILURE(rc)) 4521 4376 goto out; … … 4530 4385 uFileOffset = RT_ALIGN_64(uFileOffset, 512); 4531 4386 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, 4532 uFileOffset );4387 uFileOffset, pIoCtx); 4533 4388 if (RT_FAILURE(rc)) 4534 4389 goto out; … … 4563 4418 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 4564 4419 && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 4565 rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pExtent->pFile->pStorage); 4420 rc = vdIfIoIntFileFlush(pImage->pIfIo, pExtent->pFile->pStorage, pIoCtx, 4421 NULL, NULL); 4566 4422 break; 4567 4423 case VMDKETYPE_ZERO: … … 4621 4477 * number in the extent. 4622 4478 */ 4623 static int vmdkGetSector(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 4624 uint64_t uSector, uint64_t *puExtentSector) 4479 static int vmdkGetSector(PVMDKIMAGE pImage, PVDIOCTX pIoCtx, 4480 PVMDKEXTENT pExtent, uint64_t uSector, 4481 uint64_t *puExtentSector) 4625 4482 { 4626 4483 PVMDKGTCACHE pCache = pImage->pGTCache; … … 4642 4499 return VINF_SUCCESS; 4643 4500 } 4644 4645 uGDIndex = uSector / pExtent->cSectorsPerGDE;4646 if (uGDIndex >= pExtent->cGDEntries)4647 return VERR_OUT_OF_RANGE;4648 uGTSector = pExtent->pGD[uGDIndex];4649 if (!uGTSector)4650 {4651 /* There is no grain table referenced by this grain directory4652 * entry. So there is absolutely no data in this area. */4653 *puExtentSector = 0;4654 return VINF_SUCCESS;4655 }4656 4657 uGTBlock = uSector / (pExtent->cSectorsPerGrain * VMDK_GT_CACHELINE_SIZE);4658 uGTHash = vmdkGTCacheHash(pCache, uGTBlock, pExtent->uExtent);4659 pGTCacheEntry = &pCache->aGTCache[uGTHash];4660 if ( pGTCacheEntry->uExtent != pExtent->uExtent4661 || pGTCacheEntry->uGTBlock != uGTBlock)4662 {4663 /* Cache miss, fetch data from disk. */4664 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,4665 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4666 aGTDataTmp, sizeof(aGTDataTmp));4667 if (RT_FAILURE(rc))4668 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);4669 pGTCacheEntry->uExtent = pExtent->uExtent;4670 pGTCacheEntry->uGTBlock = uGTBlock;4671 for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)4672 pGTCacheEntry->aGTData[i] = RT_LE2H_U32(aGTDataTmp[i]);4673 }4674 uGTBlockIndex = (uSector / pExtent->cSectorsPerGrain) % VMDK_GT_CACHELINE_SIZE;4675 uint32_t uGrainSector = pGTCacheEntry->aGTData[uGTBlockIndex];4676 if (uGrainSector)4677 *puExtentSector = uGrainSector + uSector % pExtent->cSectorsPerGrain;4678 else4679 *puExtentSector = 0;4680 return VINF_SUCCESS;4681 }4682 4683 /**4684 * Internal. Get sector number in the extent file from the relative sector4685 * number in the extent - version for async access.4686 */4687 static int vmdkGetSectorAsync(PVMDKIMAGE pImage, PVDIOCTX pIoCtx,4688 PVMDKEXTENT pExtent, uint64_t uSector,4689 uint64_t *puExtentSector)4690 {4691 PVMDKGTCACHE pCache = pImage->pGTCache;4692 uint64_t uGDIndex, uGTSector, uGTBlock;4693 uint32_t uGTHash, uGTBlockIndex;4694 PVMDKGTCACHEENTRY pGTCacheEntry;4695 uint32_t aGTDataTmp[VMDK_GT_CACHELINE_SIZE];4696 int rc;4697 4501 4698 4502 uGDIndex = uSector / pExtent->cSectorsPerGDE; … … 4738 4542 4739 4543 /** 4740 * Internal. Allocates a new grain table (if necessary), writes the grain4741 * and updates the grain table. The cache is also updated by this operation.4742 * This is separate from vmdkGetSector, because that should be as fast as4743 * possible. Most code from vmdkGetSector also appears here.4744 */4745 static int vmdkAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,4746 uint64_t uSector, const void *pvBuf,4747 uint64_t cbWrite)4748 {4749 PVMDKGTCACHE pCache = pImage->pGTCache;4750 uint64_t uGDIndex, uGTSector, uRGTSector, uGTBlock;4751 uint64_t uFileOffset;4752 uint32_t uGTHash, uGTBlockIndex;4753 PVMDKGTCACHEENTRY pGTCacheEntry;4754 uint32_t aGTDataTmp[VMDK_GT_CACHELINE_SIZE];4755 int rc;4756 4757 uGDIndex = uSector / pExtent->cSectorsPerGDE;4758 if (uGDIndex >= pExtent->cGDEntries)4759 return VERR_OUT_OF_RANGE;4760 uGTSector = pExtent->pGD[uGDIndex];4761 if (pExtent->pRGD)4762 uRGTSector = pExtent->pRGD[uGDIndex];4763 else4764 uRGTSector = 0; /**< avoid compiler warning */4765 if (!uGTSector)4766 {4767 /* There is no grain table referenced by this grain directory4768 * entry. So there is absolutely no data in this area. Allocate4769 * a new grain table and put the reference to it in the GDs. */4770 uFileOffset = pExtent->uAppendPosition;4771 if (!uFileOffset)4772 return VERR_INTERNAL_ERROR;4773 Assert(!(uFileOffset % 512));4774 uFileOffset = RT_ALIGN_64(uFileOffset, 512);4775 uGTSector = VMDK_BYTE2SECTOR(uFileOffset);4776 4777 pExtent->uAppendPosition += pExtent->cGTEntries * sizeof(uint32_t);4778 4779 /* Normally the grain table is preallocated for hosted sparse extents4780 * that support more than 32 bit sector numbers. So this shouldn't4781 * ever happen on a valid extent. */4782 if (uGTSector > UINT32_MAX)4783 return VERR_VD_VMDK_INVALID_HEADER;4784 4785 /* Write grain table by writing the required number of grain table4786 * cache chunks. Avoids dynamic memory allocation, but is a bit4787 * slower. But as this is a pretty infrequently occurring case it4788 * should be acceptable. */4789 memset(aGTDataTmp, '\0', sizeof(aGTDataTmp));4790 for (unsigned i = 0;4791 i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE;4792 i++)4793 {4794 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,4795 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),4796 aGTDataTmp, sizeof(aGTDataTmp));4797 if (RT_FAILURE(rc))4798 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);4799 }4800 pExtent->uAppendPosition = RT_ALIGN_64( pExtent->uAppendPosition4801 + pExtent->cGTEntries * sizeof(uint32_t),4802 512);4803 4804 if (pExtent->pRGD)4805 {4806 AssertReturn(!uRGTSector, VERR_VD_VMDK_INVALID_HEADER);4807 uFileOffset = pExtent->uAppendPosition;4808 if (!uFileOffset)4809 return VERR_INTERNAL_ERROR;4810 Assert(!(uFileOffset % 512));4811 uRGTSector = VMDK_BYTE2SECTOR(uFileOffset);4812 4813 pExtent->uAppendPosition += pExtent->cGTEntries * sizeof(uint32_t);4814 4815 /* Normally the redundant grain table is preallocated for hosted4816 * sparse extents that support more than 32 bit sector numbers. So4817 * this shouldn't ever happen on a valid extent. */4818 if (uRGTSector > UINT32_MAX)4819 return VERR_VD_VMDK_INVALID_HEADER;4820 4821 /* Write backup grain table by writing the required number of grain4822 * table cache chunks. Avoids dynamic memory allocation, but is a4823 * bit slower. But as this is a pretty infrequently occurring case4824 * it should be acceptable. */4825 for (unsigned i = 0;4826 i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE;4827 i++)4828 {4829 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,4830 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),4831 aGTDataTmp, sizeof(aGTDataTmp));4832 if (RT_FAILURE(rc))4833 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);4834 }4835 4836 pExtent->uAppendPosition = pExtent->uAppendPosition4837 + pExtent->cGTEntries * sizeof(uint32_t);4838 }4839 4840 /* Update the grain directory on disk (doing it before writing the4841 * grain table will result in a garbled extent if the operation is4842 * aborted for some reason. Otherwise the worst that can happen is4843 * some unused sectors in the extent. */4844 uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector);4845 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,4846 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),4847 &uGTSectorLE, sizeof(uGTSectorLE));4848 if (RT_FAILURE(rc))4849 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);4850 if (pExtent->pRGD)4851 {4852 uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector);4853 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,4854 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),4855 &uRGTSectorLE, sizeof(uRGTSectorLE));4856 if (RT_FAILURE(rc))4857 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);4858 }4859 4860 /* As the final step update the in-memory copy of the GDs. */4861 pExtent->pGD[uGDIndex] = uGTSector;4862 if (pExtent->pRGD)4863 pExtent->pRGD[uGDIndex] = uRGTSector;4864 }4865 4866 uFileOffset = pExtent->uAppendPosition;4867 if (!uFileOffset)4868 return VERR_INTERNAL_ERROR;4869 Assert(!(uFileOffset % 512));4870 4871 /* Write the data. Always a full grain, or we're in big trouble. */4872 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)4873 {4874 if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))4875 return vdIfError(pImage->pIfError, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname);4876 4877 /* Invalidate cache, just in case some code incorrectly allows mixing4878 * of reads and writes. Normally shouldn't be needed. */4879 pExtent->uGrainSectorAbs = 0;4880 4881 /* Write compressed data block and the markers. */4882 uint32_t cbGrain = 0;4883 rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset,4884 pvBuf, cbWrite, uSector, &cbGrain);4885 if (RT_FAILURE(rc))4886 {4887 AssertRC(rc);4888 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);4889 }4890 pExtent->uLastGrainAccess = uSector / pExtent->cSectorsPerGrain;4891 pExtent->uAppendPosition += cbGrain;4892 }4893 else4894 {4895 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,4896 uFileOffset, pvBuf, cbWrite);4897 if (RT_FAILURE(rc))4898 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);4899 pExtent->uAppendPosition += cbWrite;4900 }4901 4902 /* Update the grain table (and the cache). */4903 uGTBlock = uSector / (pExtent->cSectorsPerGrain * VMDK_GT_CACHELINE_SIZE);4904 uGTHash = vmdkGTCacheHash(pCache, uGTBlock, pExtent->uExtent);4905 pGTCacheEntry = &pCache->aGTCache[uGTHash];4906 if ( pGTCacheEntry->uExtent != pExtent->uExtent4907 || pGTCacheEntry->uGTBlock != uGTBlock)4908 {4909 /* Cache miss, fetch data from disk. */4910 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,4911 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4912 aGTDataTmp, sizeof(aGTDataTmp));4913 if (RT_FAILURE(rc))4914 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);4915 pGTCacheEntry->uExtent = pExtent->uExtent;4916 pGTCacheEntry->uGTBlock = uGTBlock;4917 for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)4918 pGTCacheEntry->aGTData[i] = RT_LE2H_U32(aGTDataTmp[i]);4919 }4920 else4921 {4922 /* Cache hit. Convert grain table block back to disk format, otherwise4923 * the code below will write garbage for all but the updated entry. */4924 for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)4925 aGTDataTmp[i] = RT_H2LE_U32(pGTCacheEntry->aGTData[i]);4926 }4927 uGTBlockIndex = (uSector / pExtent->cSectorsPerGrain) % VMDK_GT_CACHELINE_SIZE;4928 aGTDataTmp[uGTBlockIndex] = RT_H2LE_U32(VMDK_BYTE2SECTOR(uFileOffset));4929 pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(uFileOffset);4930 /* Update grain table on disk. */4931 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,4932 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4933 aGTDataTmp, sizeof(aGTDataTmp));4934 if (RT_FAILURE(rc))4935 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);4936 if (pExtent->pRGD)4937 {4938 /* Update backup grain table on disk. */4939 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,4940 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4941 aGTDataTmp, sizeof(aGTDataTmp));4942 if (RT_FAILURE(rc))4943 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);4944 }4945 #ifdef VBOX_WITH_VMDK_ESX4946 if (RT_SUCCESS(rc) && pExtent->enmType == VMDKETYPE_ESX_SPARSE)4947 {4948 pExtent->uFreeSector = uGTSector + VMDK_BYTE2SECTOR(cbWrite);4949 pExtent->fMetaDirty = true;4950 }4951 #endif /* VBOX_WITH_VMDK_ESX */4952 return rc;4953 }4954 4955 /**4956 4544 * Internal. Writes the grain and also if necessary the grain tables. 4957 4545 * Uses the grain table cache as a true grain table. 4958 4546 */ 4959 4547 static int vmdkStreamAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 4960 uint64_t uSector, const void *pvBuf,4548 uint64_t uSector, PVDIOCTX pIoCtx, 4961 4549 uint64_t cbWrite) 4962 4550 { … … 4965 4553 uint32_t cbGrain = 0; 4966 4554 uint32_t uCacheLine, uCacheEntry; 4967 const void *pData = pvBuf;4555 const void *pData; 4968 4556 int rc; 4969 4557 … … 4996 4584 * to allocate something, we also need to detect the situation ourself. */ 4997 4585 if ( !(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_ZEROES) 4998 && ASMBitFirstSet((volatile void *)pvBuf, (uint32_t)cbWrite * 8) == -1)4586 && vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbWrite, true /* fAdvance */)) 4999 4587 return VINF_SUCCESS; 5000 4588 … … 5033 4621 if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)) 5034 4622 { 5035 memcpy(pExtent->pvGrain, pvBuf, cbWrite);4623 vdIfIoIntIoCtxCopyFrom(pImage->pIfIo, pIoCtx, pExtent->pvGrain, cbWrite); 5036 4624 memset((char *)pExtent->pvGrain + cbWrite, '\0', 5037 4625 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain) - cbWrite); 5038 4626 pData = pExtent->pvGrain; 5039 4627 } 4628 else 4629 { 4630 RTSGSEG Segment; 4631 unsigned cSegments = 1; 4632 size_t cbSeg = 0; 4633 4634 cbSeg = vdIfIoIntIoCtxSegArrayCreate(pImage->pIfIo, pIoCtx, &Segment, 4635 &cSegments, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 4636 Assert(cbSeg == VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 4637 pData = Segment.pvSeg; 4638 } 5040 4639 rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset, pData, 5041 4640 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), … … 5054 4653 5055 4654 /** 5056 * Internal: Updates the grain table during a asyncgrain allocation.4655 * Internal: Updates the grain table during grain allocation. 5057 4656 */ 5058 static int vmdkAllocGrainAsyncGTUpdate(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 5059 PVDIOCTX pIoCtx, 5060 PVMDKGRAINALLOCASYNC pGrainAlloc) 4657 static int vmdkAllocGrainGTUpdate(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, PVDIOCTX pIoCtx, 4658 PVMDKGRAINALLOCASYNC pGrainAlloc) 5061 4659 { 5062 4660 int rc = VINF_SUCCESS; … … 5088 4686 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 5089 4687 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 5090 &pMetaXfer, vmdkAllocGrain AsyncComplete, pGrainAlloc);4688 &pMetaXfer, vmdkAllocGrainComplete, pGrainAlloc); 5091 4689 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5092 4690 { … … 5120 4718 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 5121 4719 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 5122 vmdkAllocGrain AsyncComplete, pGrainAlloc);4720 vmdkAllocGrainComplete, pGrainAlloc); 5123 4721 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5124 4722 pGrainAlloc->cIoXfersPending++; … … 5131 4729 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 5132 4730 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 5133 vmdkAllocGrain AsyncComplete, pGrainAlloc);4731 vmdkAllocGrainComplete, pGrainAlloc); 5134 4732 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5135 4733 pGrainAlloc->cIoXfersPending++; … … 5153 4751 * Internal - complete the grain allocation by updating disk grain table if required. 5154 4752 */ 5155 static int vmdkAllocGrain AsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)4753 static int vmdkAllocGrainComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 5156 4754 { 5157 4755 int rc = VINF_SUCCESS; … … 5165 4763 pGrainAlloc->cIoXfersPending--; 5166 4764 if (!pGrainAlloc->cIoXfersPending && pGrainAlloc->fGTUpdateNeeded) 5167 rc = vmdkAllocGrainAsyncGTUpdate(pImage, pGrainAlloc->pExtent, 5168 pIoCtx, pGrainAlloc); 4765 rc = vmdkAllocGrainGTUpdate(pImage, pGrainAlloc->pExtent, pIoCtx, pGrainAlloc); 5169 4766 5170 4767 if (!pGrainAlloc->cIoXfersPending) … … 5179 4776 5180 4777 /** 5181 * Internal. Allocates a new grain table (if necessary) - async version.4778 * Internal. Allocates a new grain table (if necessary). 5182 4779 */ 5183 static int vmdkAllocGrainAsync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 5184 PVDIOCTX pIoCtx, uint64_t uSector, 5185 uint64_t cbWrite) 4780 static int vmdkAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, PVDIOCTX pIoCtx, 4781 uint64_t uSector, uint64_t cbWrite) 5186 4782 { 5187 4783 PVMDKGTCACHE pCache = pImage->pGTCache; … … 5193 4789 LogFlowFunc(("pCache=%#p pExtent=%#p pIoCtx=%#p uSector=%llu cbWrite=%llu\n", 5194 4790 pCache, pExtent, pIoCtx, uSector, cbWrite)); 5195 5196 AssertReturn(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), VERR_NOT_SUPPORTED);5197 4791 5198 4792 pGrainAlloc = (PVMDKGRAINALLOCASYNC)RTMemAllocZ(sizeof(VMDKGRAINALLOCASYNC)); … … 5248 4842 VMDK_SECTOR2BYTE(uGTSector), 5249 4843 paGTDataTmp, cbGTDataTmp, pIoCtx, 5250 vmdkAllocGrain AsyncComplete, pGrainAlloc);4844 vmdkAllocGrainComplete, pGrainAlloc); 5251 4845 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5252 4846 pGrainAlloc->cIoXfersPending++; … … 5283 4877 VMDK_SECTOR2BYTE(uRGTSector), 5284 4878 paGTDataTmp, cbGTDataTmp, pIoCtx, 5285 vmdkAllocGrain AsyncComplete, pGrainAlloc);4879 vmdkAllocGrainComplete, pGrainAlloc); 5286 4880 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5287 4881 pGrainAlloc->cIoXfersPending++; … … 5305 4899 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), 5306 4900 &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx, 5307 vmdkAllocGrain AsyncComplete, pGrainAlloc);4901 vmdkAllocGrainComplete, pGrainAlloc); 5308 4902 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5309 4903 pGrainAlloc->cIoXfersPending++; … … 5316 4910 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE), 5317 4911 &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx, 5318 vmdkAllocGrain AsyncComplete, pGrainAlloc);4912 vmdkAllocGrainComplete, pGrainAlloc); 5319 4913 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5320 4914 pGrainAlloc->cIoXfersPending++; … … 5340 4934 pGrainAlloc->uGrainOffset = uFileOffset; 5341 4935 5342 /* Write the data. Always a full grain, or we're in big trouble. */ 5343 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage, 5344 uFileOffset, pIoCtx, cbWrite, 5345 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5346 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5347 pGrainAlloc->cIoXfersPending++; 5348 else if (RT_FAILURE(rc)) 5349 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname); 5350 5351 pExtent->uAppendPosition += cbWrite; 5352 5353 rc = vmdkAllocGrainAsyncGTUpdate(pImage, pExtent, pIoCtx, pGrainAlloc); 4936 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 4937 { 4938 AssertMsgReturn(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx), 4939 ("Accesses to stream optimized images must be synchronous\n"), 4940 VERR_INVALID_STATE); 4941 4942 if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)) 4943 return vdIfError(pImage->pIfError, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname); 4944 4945 /* Invalidate cache, just in case some code incorrectly allows mixing 4946 * of reads and writes. Normally shouldn't be needed. */ 4947 pExtent->uGrainSectorAbs = 0; 4948 4949 /* Write compressed data block and the markers. */ 4950 uint32_t cbGrain = 0; 4951 size_t cbSeg = 0; 4952 RTSGSEG Segment; 4953 unsigned cSegments = 1; 4954 4955 cbSeg = vdIfIoIntIoCtxSegArrayCreate(pImage->pIfIo, pIoCtx, &Segment, 4956 &cSegments, cbWrite); 4957 Assert(cbSeg == cbWrite); 4958 4959 rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset, 4960 Segment.pvSeg, cbWrite, uSector, &cbGrain); 4961 if (RT_FAILURE(rc)) 4962 { 4963 AssertRC(rc); 4964 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname); 4965 } 4966 pExtent->uLastGrainAccess = uSector / pExtent->cSectorsPerGrain; 4967 pExtent->uAppendPosition += cbGrain; 4968 } 4969 else 4970 { 4971 /* Write the data. Always a full grain, or we're in big trouble. */ 4972 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage, 4973 uFileOffset, pIoCtx, cbWrite, 4974 vmdkAllocGrainComplete, pGrainAlloc); 4975 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 4976 pGrainAlloc->cIoXfersPending++; 4977 else if (RT_FAILURE(rc)) 4978 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname); 4979 4980 pExtent->uAppendPosition += cbWrite; 4981 } 4982 4983 rc = vmdkAllocGrainGTUpdate(pImage, pExtent, pIoCtx, pGrainAlloc); 5354 4984 5355 4985 if (!pGrainAlloc->cIoXfersPending) … … 5369 4999 */ 5370 5000 static int vmdkStreamReadSequential(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 5371 uint64_t uSector, void *pvBuf,5001 uint64_t uSector, PVDIOCTX pIoCtx, 5372 5002 uint64_t cbRead) 5373 5003 { 5374 5004 int rc; 5375 5005 5376 LogFlowFunc(("pImage=%#p pExtent=%#p uSector=%llu pvBuf=%#p cbRead=%llu\n", 5377 pImage, pExtent, uSector, pvBuf, cbRead)); 5006 LogFlowFunc(("pImage=%#p pExtent=%#p uSector=%llu pIoCtx=%#p cbRead=%llu\n", 5007 pImage, pExtent, uSector, pIoCtx, cbRead)); 5008 5009 AssertMsgReturn(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx), 5010 ("Async I/O not supported for sequential stream optimized images\n"), 5011 VERR_INVALID_STATE); 5378 5012 5379 5013 /* Do not allow to go back. */ … … 5509 5143 5510 5144 uint32_t uSectorInGrain = uSector % pExtent->cSectorsPerGrain; 5511 memcpy(pvBuf,5512 (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain),5513 cbRead);5145 vdIfIoIntIoCtxCopyTo(pImage->pIfIo, pIoCtx, 5146 (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), 5147 cbRead); 5514 5148 LogFlowFunc(("returns VINF_SUCCESS\n")); 5515 5149 return VINF_SUCCESS; … … 5871 5505 pImage->Descriptor.fDirty = true; 5872 5506 /* Flush the descriptor now, in case it is embedded. */ 5873 vmdkFlushImage(pImage );5507 vmdkFlushImage(pImage, NULL); 5874 5508 5875 5509 /* Close and rename/move extents. */ … … 5944 5578 rrc = vmdkFileOpen(pImage, &pFile, pszOldDescName, 5945 5579 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_NORMAL, 5946 false /* fCreate */), 5947 false /* fAsyncIO */); 5580 false /* fCreate */)); 5948 5581 AssertRC(rrc); 5949 5582 if (fEmbeddedDesc) … … 5961 5594 } 5962 5595 pImage->Descriptor = DescriptorCopy; 5963 vmdkWriteDescriptor(pImage );5596 vmdkWriteDescriptor(pImage, NULL); 5964 5597 vmdkFileClose(pImage, &pFile, false); 5965 5598 /* Get rid of the stuff we implanted. */ … … 6027 5660 6028 5661 /** @copydoc VBOXHDDBACKEND::pfnRead */ 6029 static int vmdkRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 6030 size_t cbToRead, size_t *pcbActuallyRead) 6031 { 6032 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 5662 static int vmdkRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 5663 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 5664 { 5665 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 5666 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 6033 5667 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 6034 5668 PVMDKEXTENT pExtent; … … 6070 5704 case VMDKETYPE_ESX_SPARSE: 6071 5705 #endif /* VBOX_WITH_VMDK_ESX */ 6072 rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel, 6073 &uSectorExtentAbs); 5706 rc = vmdkGetSector(pImage, pIoCtx, pExtent, uSectorExtentRel, &uSectorExtentAbs); 6074 5707 if (RT_FAILURE(rc)) 6075 5708 goto out; … … 6086 5719 rc = vmdkStreamReadSequential(pImage, pExtent, 6087 5720 uSectorExtentRel, 6088 p vBuf, cbToRead);5721 pIoCtx, cbToRead); 6089 5722 } 6090 5723 else … … 6092 5725 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 6093 5726 { 5727 AssertMsg(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx), 5728 ("Async I/O is not supported for stream optimized VMDK's\n")); 5729 6094 5730 uint32_t uSectorInGrain = uSectorExtentRel % pExtent->cSectorsPerGrain; 6095 5731 uSectorExtentAbs -= uSectorInGrain; … … 6112 5748 Assert(uLBA == uSectorExtentRel); 6113 5749 } 6114 memcpy(pvBuf, (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), cbToRead); 5750 vdIfIoIntIoCtxCopyTo(pImage->pIfIo, pIoCtx, 5751 (uint8_t *)pExtent->pvGrain 5752 + VMDK_SECTOR2BYTE(uSectorInGrain), 5753 cbToRead); 6115 5754 } 6116 5755 else 6117 { 6118 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage, 5756 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage, 6119 5757 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6120 pvBuf, cbToRead); 6121 } 5758 pIoCtx, cbToRead); 6122 5759 } 6123 5760 break; 6124 5761 case VMDKETYPE_VMFS: 6125 5762 case VMDKETYPE_FLAT: 6126 rc = vdIfIoIntFileRead Sync(pImage->pIfIo, pExtent->pFile->pStorage,5763 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage, 6127 5764 VMDK_SECTOR2BYTE(uSectorExtentRel), 6128 p vBuf, cbToRead);5765 pIoCtx, cbToRead); 6129 5766 break; 6130 5767 case VMDKETYPE_ZERO: 6131 memset(pvBuf, '\0', cbToRead); 5768 size_t cbSet; 5769 5770 cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); 5771 Assert(cbSet == cbToRead); 5772 5773 rc = VINF_SUCCESS; 6132 5774 break; 6133 5775 } … … 6141 5783 6142 5784 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 6143 static int vmdkWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 6144 size_t cbToWrite, size_t *pcbWriteProcess, 6145 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 6146 { 6147 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 5785 static int vmdkWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 5786 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, 5787 size_t *pcbPostRead, unsigned fWrite) 5788 { 5789 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 5790 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 6148 5791 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 6149 5792 PVMDKEXTENT pExtent; … … 6197 5840 case VMDKETYPE_ESX_SPARSE: 6198 5841 #endif /* VBOX_WITH_VMDK_ESX */ 6199 rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel, 6200 &uSectorExtentAbs); 5842 rc = vmdkGetSector(pImage, pIoCtx, pExtent, uSectorExtentRel, &uSectorExtentAbs); 6201 5843 if (RT_FAILURE(rc)) 6202 5844 goto out; … … 6216 5858 { 6217 5859 /* Full block write to a previously unallocated block. 6218 * Check if the caller wants feedback. */5860 * Check if the caller wants to avoid the automatic alloc. */ 6219 5861 if (!(fWrite & VD_WRITE_NO_ALLOC)) 6220 5862 { 6221 /* Allocate GT and store the grain. */ 6222 rc = vmdkAllocGrain(pImage, pExtent, 6223 uSectorExtentRel, 6224 pvBuf, cbToWrite); 5863 /* Allocate GT and find out where to store the grain. */ 5864 rc = vmdkAllocGrain(pImage, pExtent, pIoCtx, 5865 uSectorExtentRel, cbToWrite); 6225 5866 } 6226 5867 else … … 6242 5883 rc = vmdkStreamAllocGrain(pImage, pExtent, 6243 5884 uSectorExtentRel, 6244 p vBuf, cbToWrite);5885 pIoCtx, cbToWrite); 6245 5886 } 6246 5887 } … … 6258 5899 else 6259 5900 { 6260 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage, 5901 Assert(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)); 5902 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage, 6261 5903 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6262 p vBuf, cbToWrite);5904 pIoCtx, cbToWrite, NULL, NULL); 6263 5905 } 6264 5906 } … … 6268 5910 /* Clip write range to remain in this extent. */ 6269 5911 cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 6270 rc = vdIfIoIntFileWrite Sync(pImage->pIfIo, pExtent->pFile->pStorage,5912 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage, 6271 5913 VMDK_SECTOR2BYTE(uSectorExtentRel), 6272 p vBuf, cbToWrite);5914 pIoCtx, cbToWrite, NULL, NULL); 6273 5915 break; 6274 5916 case VMDKETYPE_ZERO: … … 6287 5929 6288 5930 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 6289 static int vmdkFlush(void *pBackendData) 6290 { 6291 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 5931 static int vmdkFlush(void *pBackendData, PVDIOCTX pIoCtx) 5932 { 6292 5933 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 6293 int rc = VINF_SUCCESS; 6294 6295 AssertPtr(pImage); 6296 6297 if (!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)) 6298 rc = vmdkFlushImage(pImage); 6299 6300 LogFlowFunc(("returns %Rrc\n", rc)); 6301 return rc; 5934 5935 return vmdkFlushImage(pImage, pIoCtx); 6302 5936 } 6303 5937 … … 6876 6510 } 6877 6511 6878 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */6879 static int vmdkAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,6880 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)6881 {6882 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",6883 pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead));6884 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;6885 PVMDKEXTENT pExtent;6886 uint64_t uSectorExtentRel;6887 uint64_t uSectorExtentAbs;6888 int rc;6889 6890 AssertPtr(pImage);6891 Assert(uOffset % 512 == 0);6892 Assert(cbRead % 512 == 0);6893 6894 if ( uOffset + cbRead > pImage->cbSize6895 || cbRead == 0)6896 {6897 rc = VERR_INVALID_PARAMETER;6898 goto out;6899 }6900 6901 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset),6902 &pExtent, &uSectorExtentRel);6903 if (RT_FAILURE(rc))6904 goto out;6905 6906 /* Check access permissions as defined in the extent descriptor. */6907 if (pExtent->enmAccess == VMDKACCESS_NOACCESS)6908 {6909 rc = VERR_VD_VMDK_INVALID_STATE;6910 goto out;6911 }6912 6913 /* Clip read range to remain in this extent. */6914 cbRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));6915 6916 /* Handle the read according to the current extent type. */6917 switch (pExtent->enmType)6918 {6919 case VMDKETYPE_HOSTED_SPARSE:6920 #ifdef VBOX_WITH_VMDK_ESX6921 case VMDKETYPE_ESX_SPARSE:6922 #endif /* VBOX_WITH_VMDK_ESX */6923 rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent,6924 uSectorExtentRel, &uSectorExtentAbs);6925 if (RT_FAILURE(rc))6926 goto out;6927 /* Clip read range to at most the rest of the grain. */6928 cbRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));6929 Assert(!(cbRead % 512));6930 if (uSectorExtentAbs == 0)6931 rc = VERR_VD_BLOCK_FREE;6932 else6933 {6934 AssertMsg(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), ("Async I/O is not supported for stream optimized VMDK's\n"));6935 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage,6936 VMDK_SECTOR2BYTE(uSectorExtentAbs),6937 pIoCtx, cbRead);6938 }6939 break;6940 case VMDKETYPE_VMFS:6941 case VMDKETYPE_FLAT:6942 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage,6943 VMDK_SECTOR2BYTE(uSectorExtentRel),6944 pIoCtx, cbRead);6945 break;6946 case VMDKETYPE_ZERO:6947 size_t cbSet;6948 6949 cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbRead);6950 Assert(cbSet == cbRead);6951 6952 rc = VINF_SUCCESS;6953 break;6954 }6955 if (pcbActuallyRead)6956 *pcbActuallyRead = cbRead;6957 6958 out:6959 LogFlowFunc(("returns %Rrc\n", rc));6960 return rc;6961 }6962 6963 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */6964 static int vmdkAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,6965 PVDIOCTX pIoCtx,6966 size_t *pcbWriteProcess, size_t *pcbPreRead,6967 size_t *pcbPostRead, unsigned fWrite)6968 {6969 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",6970 pBackendData, uOffset, pIoCtx, cbWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));6971 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;6972 PVMDKEXTENT pExtent;6973 uint64_t uSectorExtentRel;6974 uint64_t uSectorExtentAbs;6975 int rc;6976 6977 AssertPtr(pImage);6978 Assert(uOffset % 512 == 0);6979 Assert(cbWrite % 512 == 0);6980 6981 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)6982 {6983 rc = VERR_VD_IMAGE_READ_ONLY;6984 goto out;6985 }6986 6987 if (cbWrite == 0)6988 {6989 rc = VERR_INVALID_PARAMETER;6990 goto out;6991 }6992 6993 /* No size check here, will do that later when the extent is located.6994 * There are sparse images out there which according to the spec are6995 * invalid, because the total size is not a multiple of the grain size.6996 * Also for sparse images which are stitched together in odd ways (not at6997 * grain boundaries, and with the nominal size not being a multiple of the6998 * grain size), this would prevent writing to the last grain. */6999 7000 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset),7001 &pExtent, &uSectorExtentRel);7002 if (RT_FAILURE(rc))7003 goto out;7004 7005 /* Check access permissions as defined in the extent descriptor. */7006 if (pExtent->enmAccess != VMDKACCESS_READWRITE)7007 {7008 rc = VERR_VD_VMDK_INVALID_STATE;7009 goto out;7010 }7011 7012 /* Handle the write according to the current extent type. */7013 switch (pExtent->enmType)7014 {7015 case VMDKETYPE_HOSTED_SPARSE:7016 #ifdef VBOX_WITH_VMDK_ESX7017 case VMDKETYPE_ESX_SPARSE:7018 #endif /* VBOX_WITH_VMDK_ESX */7019 rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent, uSectorExtentRel,7020 &uSectorExtentAbs);7021 if (RT_FAILURE(rc))7022 goto out;7023 /* Clip write range to at most the rest of the grain. */7024 cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));7025 if ( pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED7026 && uSectorExtentRel < (uint64_t)pExtent->uLastGrainAccess * pExtent->cSectorsPerGrain)7027 {7028 rc = VERR_VD_VMDK_INVALID_WRITE;7029 goto out;7030 }7031 if (uSectorExtentAbs == 0)7032 {7033 if (cbWrite == VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))7034 {7035 /* Full block write to a previously unallocated block.7036 * Check if the caller wants to avoid the automatic alloc. */7037 if (!(fWrite & VD_WRITE_NO_ALLOC))7038 {7039 /* Allocate GT and find out where to store the grain. */7040 rc = vmdkAllocGrainAsync(pImage, pExtent, pIoCtx,7041 uSectorExtentRel, cbWrite);7042 }7043 else7044 rc = VERR_VD_BLOCK_FREE;7045 *pcbPreRead = 0;7046 *pcbPostRead = 0;7047 }7048 else7049 {7050 /* Clip write range to remain in this extent. */7051 cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));7052 *pcbPreRead = VMDK_SECTOR2BYTE(uSectorExtentRel % pExtent->cSectorsPerGrain);7053 *pcbPostRead = VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain) - cbWrite - *pcbPreRead;7054 rc = VERR_VD_BLOCK_FREE;7055 }7056 }7057 else7058 {7059 Assert(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED));7060 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,7061 VMDK_SECTOR2BYTE(uSectorExtentAbs),7062 pIoCtx, cbWrite, NULL, NULL);7063 }7064 break;7065 case VMDKETYPE_VMFS:7066 case VMDKETYPE_FLAT:7067 /* Clip write range to remain in this extent. */7068 cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));7069 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,7070 VMDK_SECTOR2BYTE(uSectorExtentRel),7071 pIoCtx, cbWrite, NULL, NULL);7072 break;7073 case VMDKETYPE_ZERO:7074 /* Clip write range to remain in this extent. */7075 cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));7076 break;7077 }7078 7079 if (pcbWriteProcess)7080 *pcbWriteProcess = cbWrite;7081 7082 out:7083 LogFlowFunc(("returns %Rrc\n", rc));7084 return rc;7085 }7086 7087 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */7088 static int vmdkAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)7089 {7090 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;7091 PVMDKEXTENT pExtent;7092 int rc = VINF_SUCCESS;7093 7094 /* Update descriptor if changed. */7095 /** @todo: The descriptor is never updated because7096 * it remains unchanged during normal operation (only vmdkRename updates it).7097 * So this part is actually not tested so far and requires testing as soon7098 * as the descriptor might change during async I/O.7099 */7100 if (pImage->Descriptor.fDirty)7101 {7102 rc = vmdkWriteDescriptorAsync(pImage, pIoCtx);7103 if ( RT_FAILURE(rc)7104 && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)7105 goto out;7106 }7107 7108 for (unsigned i = 0; i < pImage->cExtents; i++)7109 {7110 pExtent = &pImage->pExtents[i];7111 if (pExtent->pFile != NULL && pExtent->fMetaDirty)7112 {7113 switch (pExtent->enmType)7114 {7115 case VMDKETYPE_HOSTED_SPARSE:7116 #ifdef VBOX_WITH_VMDK_ESX7117 case VMDKETYPE_ESX_SPARSE:7118 #endif /* VBOX_WITH_VMDK_ESX */7119 rc = vmdkWriteMetaSparseExtentAsync(pImage, pExtent, 0, pIoCtx);7120 if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))7121 goto out;7122 if (pExtent->fFooter)7123 {7124 uint64_t uFileOffset = pExtent->uAppendPosition;7125 if (!uFileOffset)7126 {7127 rc = VERR_INTERNAL_ERROR;7128 goto out;7129 }7130 uFileOffset = RT_ALIGN_64(uFileOffset, 512);7131 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, uFileOffset);7132 if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))7133 goto out;7134 }7135 break;7136 case VMDKETYPE_VMFS:7137 case VMDKETYPE_FLAT:7138 /* Nothing to do. */7139 break;7140 case VMDKETYPE_ZERO:7141 default:7142 AssertMsgFailed(("extent with type %d marked as dirty\n",7143 pExtent->enmType));7144 break;7145 }7146 }7147 switch (pExtent->enmType)7148 {7149 case VMDKETYPE_HOSTED_SPARSE:7150 #ifdef VBOX_WITH_VMDK_ESX7151 case VMDKETYPE_ESX_SPARSE:7152 #endif /* VBOX_WITH_VMDK_ESX */7153 case VMDKETYPE_VMFS:7154 case VMDKETYPE_FLAT:7155 /*7156 * Don't ignore block devices like in the sync case7157 * (they have an absolute path).7158 * We might have unwritten data in the writeback cache and7159 * the async I/O manager will handle these requests properly7160 * even if the block device doesn't support these requests.7161 */7162 if ( pExtent->pFile != NULL7163 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))7164 rc = vdIfIoIntFileFlush(pImage->pIfIo, pExtent->pFile->pStorage,7165 pIoCtx, NULL, NULL);7166 break;7167 case VMDKETYPE_ZERO:7168 /* No need to do anything for this extent. */7169 break;7170 default:7171 AssertMsgFailed(("unknown extent type %d\n", pExtent->enmType));7172 break;7173 }7174 }7175 7176 out:7177 return rc;7178 }7179 6512 7180 6513 … … 7211 6544 /* pfnFlush */ 7212 6545 vmdkFlush, 6546 /* pfnDiscard */ 6547 NULL, 7213 6548 /* pfnGetVersion */ 7214 6549 vmdkGetVersion, … … 7263 6598 /* pfnSetParentFilename */ 7264 6599 NULL, 7265 /* pfnAsyncRead */7266 vmdkAsyncRead,7267 /* pfnAsyncWrite */7268 vmdkAsyncWrite,7269 /* pfnAsyncFlush */7270 vmdkAsyncFlush,7271 6600 /* pfnComposeLocation */ 7272 6601 genericFileComposeLocation, … … 7277 6606 /* pfnResize */ 7278 6607 NULL, 7279 /* pfnDiscard */7280 NULL,7281 /* pfnAsyncDiscard */7282 NULL,7283 6608 /* pfnRepair */ 7284 6609 NULL
Note:
See TracChangeset
for help on using the changeset viewer.