- Timestamp:
- Sep 12, 2016 10:13:44 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/QCOW.cpp
r63785 r63793 452 452 } 453 453 454 #if 0 /* unused */455 /**456 * Convert refcount table entries from little endian to host endianess.457 *458 * @returns nothing.459 * @param paTbl Pointer to the table.460 * @param cEntries Number of entries in the table.461 */462 static void qcowRefcountTableConvertToHostEndianess(uint16_t *paTbl, uint32_t cEntries)463 {464 while(cEntries-- > 0)465 {466 *paTbl = RT_BE2H_U16(*paTbl);467 paTbl++;468 }469 }470 #endif471 472 #if 0 /* unused */473 /**474 * Convert table entries from host to little endian format.475 *476 * @returns nothing.477 * @param paTblImg Pointer to the table which will store the little endian table.478 * @param paTbl The source table to convert.479 * @param cEntries Number of entries in the table.480 */481 static void qcowRefcountTableConvertFromHostEndianess(uint16_t *paTblImg, uint16_t *paTbl,482 uint32_t cEntries)483 {484 while(cEntries-- > 0)485 {486 *paTblImg = RT_H2BE_U16(*paTbl);487 paTbl++;488 paTblImg++;489 }490 }491 #endif492 493 454 /** 494 455 * Creates the L2 table cache. … … 975 936 976 937 /** 977 * Flush image data to disk - version for async I/O.978 *979 * @returns VBox status code.980 * @param pImage The image instance data.981 * @param pIoCtx The I/o context982 */983 static int qcowFlushImageAsync(PQCOWIMAGE pImage, PVDIOCTX pIoCtx)984 {985 int rc = VINF_SUCCESS;986 987 if ( pImage->pStorage988 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))989 {990 QCowHeader Header;991 992 rc = qcowTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table,993 pImage->cbL1Table, pImage->cL1TableEntries, NULL, NULL);994 if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)995 {996 /* Write header. */997 size_t cbHeader = 0;998 qcowHdrConvertFromHostEndianess(pImage, &Header, &cbHeader);999 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,1000 0, &Header, cbHeader,1001 pIoCtx, NULL, NULL);1002 if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)1003 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage,1004 pIoCtx, NULL, NULL);1005 }1006 }1007 1008 return rc;1009 }1010 1011 /**1012 938 * Internal. Free all allocated space for representing an image except pImage, 1013 939 * and optionally delete the image from disk. … … 1112 1038 static int qcowOpenImage(PQCOWIMAGE pImage, unsigned uOpenFlags) 1113 1039 { 1114 int rc;1115 1116 1040 pImage->uOpenFlags = uOpenFlags; 1117 1041 … … 1120 1044 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); 1121 1045 1122 rc = qcowL2TblCacheCreate(pImage); 1123 AssertRC(rc); 1124 1125 /* 1126 * Open the image. 1127 */ 1128 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, 1129 VDOpenFlagsToFileOpenFlags(uOpenFlags, 1130 false /* fCreate */), 1131 &pImage->pStorage); 1132 if (RT_FAILURE(rc)) 1133 { 1134 /* Do NOT signal an appropriate error here, as the VD layer has the 1135 * choice of retrying the open if it failed. */ 1136 goto out; 1137 } 1138 1139 uint64_t cbFile; 1140 QCowHeader Header; 1141 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 1142 if (RT_FAILURE(rc)) 1143 goto out; 1144 if (cbFile > sizeof(Header)) 1145 { 1146 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0, &Header, sizeof(Header)); 1147 if ( RT_SUCCESS(rc) 1148 && qcowHdrConvertToHostEndianess(&Header)) 1149 { 1150 pImage->offNextCluster = RT_ALIGN_64(cbFile, 512); /* Align image to sector boundary. */ 1151 Assert(pImage->offNextCluster >= cbFile); 1152 1153 rc = qcowHdrValidate(pImage, &Header, cbFile); 1154 if (RT_SUCCESS(rc)) 1046 int rc = qcowL2TblCacheCreate(pImage); 1047 if (RT_SUCCESS(rc)) 1048 { 1049 /* Open the image. */ 1050 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, 1051 VDOpenFlagsToFileOpenFlags(uOpenFlags, 1052 false /* fCreate */), 1053 &pImage->pStorage); 1054 if (RT_SUCCESS(rc)) 1055 { 1056 uint64_t cbFile; 1057 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 1058 if ( RT_SUCCESS(rc) 1059 && cbFile > sizeof(QCowHeader)) 1155 1060 { 1156 if (Header.u32Version == 1) 1061 QCowHeader Header; 1062 1063 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0, &Header, sizeof(Header)); 1064 if ( RT_SUCCESS(rc) 1065 && qcowHdrConvertToHostEndianess(&Header)) 1157 1066 { 1158 if (!Header.Version.v1.u32CryptMethod) 1067 pImage->offNextCluster = RT_ALIGN_64(cbFile, 512); /* Align image to sector boundary. */ 1068 Assert(pImage->offNextCluster >= cbFile); 1069 1070 rc = qcowHdrValidate(pImage, &Header, cbFile); 1071 if (RT_SUCCESS(rc)) 1159 1072 { 1160 pImage->uVersion = 1; 1161 pImage->offBackingFilename = Header.Version.v1.u64BackingFileOffset; 1162 pImage->cbBackingFilename = Header.Version.v1.u32BackingFileSize; 1163 pImage->MTime = Header.Version.v1.u32MTime; 1164 pImage->cbSize = Header.Version.v1.u64Size; 1165 pImage->cbCluster = RT_BIT_32(Header.Version.v1.u8ClusterBits); 1166 pImage->cL2TableEntries = RT_BIT_32(Header.Version.v1.u8L2Bits); 1167 pImage->cbL2Table = RT_ALIGN_64(pImage->cL2TableEntries * sizeof(uint64_t), pImage->cbCluster); 1168 pImage->offL1Table = Header.Version.v1.u64L1TableOffset; 1169 pImage->cL1TableEntries = pImage->cbSize / (pImage->cbCluster * pImage->cL2TableEntries); 1170 if (pImage->cbSize % (pImage->cbCluster * pImage->cL2TableEntries)) 1171 pImage->cL1TableEntries++; 1073 if (Header.u32Version == 1) 1074 { 1075 if (!Header.Version.v1.u32CryptMethod) 1076 { 1077 pImage->uVersion = 1; 1078 pImage->offBackingFilename = Header.Version.v1.u64BackingFileOffset; 1079 pImage->cbBackingFilename = Header.Version.v1.u32BackingFileSize; 1080 pImage->MTime = Header.Version.v1.u32MTime; 1081 pImage->cbSize = Header.Version.v1.u64Size; 1082 pImage->cbCluster = RT_BIT_32(Header.Version.v1.u8ClusterBits); 1083 pImage->cL2TableEntries = RT_BIT_32(Header.Version.v1.u8L2Bits); 1084 pImage->cbL2Table = RT_ALIGN_64(pImage->cL2TableEntries * sizeof(uint64_t), pImage->cbCluster); 1085 pImage->offL1Table = Header.Version.v1.u64L1TableOffset; 1086 pImage->cL1TableEntries = pImage->cbSize / (pImage->cbCluster * pImage->cL2TableEntries); 1087 if (pImage->cbSize % (pImage->cbCluster * pImage->cL2TableEntries)) 1088 pImage->cL1TableEntries++; 1089 } 1090 else 1091 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1092 N_("QCow: Encrypted image '%s' is not supported"), 1093 pImage->pszFilename); 1094 } 1095 else if (Header.u32Version == 2) 1096 { 1097 if (Header.Version.v2.u32CryptMethod) 1098 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1099 N_("QCow: Encrypted image '%s' is not supported"), 1100 pImage->pszFilename); 1101 else if (Header.Version.v2.u32NbSnapshots) 1102 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1103 N_("QCow: Image '%s' contains snapshots which is not supported"), 1104 pImage->pszFilename); 1105 else 1106 { 1107 pImage->uVersion = 2; 1108 pImage->offBackingFilename = Header.Version.v2.u64BackingFileOffset; 1109 pImage->cbBackingFilename = Header.Version.v2.u32BackingFileSize; 1110 pImage->cbSize = Header.Version.v2.u64Size; 1111 pImage->cbCluster = RT_BIT_32(Header.Version.v2.u32ClusterBits); 1112 pImage->cL2TableEntries = pImage->cbCluster / sizeof(uint64_t); 1113 pImage->cbL2Table = pImage->cbCluster; 1114 pImage->offL1Table = Header.Version.v2.u64L1TableOffset; 1115 pImage->cL1TableEntries = Header.Version.v2.u32L1Size; 1116 pImage->offRefcountTable = Header.Version.v2.u64RefcountTableOffset; 1117 pImage->cbRefcountTable = qcowCluster2Byte(pImage, Header.Version.v2.u32RefcountTableClusters); 1118 pImage->cRefcountTableEntries = pImage->cbRefcountTable / sizeof(uint64_t); 1119 } 1120 } 1121 else 1122 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1123 N_("QCow: Image '%s' uses version %u which is not supported"), 1124 pImage->pszFilename, Header.u32Version); 1125 1126 pImage->cbL1Table = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster); 1127 if ((uint64_t)pImage->cbL1Table != RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster)) 1128 rc = vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS, 1129 N_("QCOW: L1 table size overflow in image '%s'"), 1130 pImage->pszFilename); 1172 1131 } 1173 else 1174 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1175 N_("QCow: Encrypted image '%s' is not supported"), 1176 pImage->pszFilename); 1177 } 1178 else if (Header.u32Version == 2) 1179 { 1180 if (Header.Version.v2.u32CryptMethod) 1181 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1182 N_("QCow: Encrypted image '%s' is not supported"), 1183 pImage->pszFilename); 1184 else if (Header.Version.v2.u32NbSnapshots) 1185 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1186 N_("QCow: Image '%s' contains snapshots which is not supported"), 1187 pImage->pszFilename); 1188 else 1132 1133 /** @todo Check that there are no compressed clusters in the image 1134 * (by traversing the L2 tables and checking each offset). 1135 * Refuse to open such images. 1136 */ 1137 1138 if ( RT_SUCCESS(rc) 1139 && pImage->cbBackingFilename 1140 && pImage->offBackingFilename) 1189 1141 { 1190 pImage->uVersion = 2; 1191 pImage->offBackingFilename = Header.Version.v2.u64BackingFileOffset; 1192 pImage->cbBackingFilename = Header.Version.v2.u32BackingFileSize; 1193 pImage->cbSize = Header.Version.v2.u64Size; 1194 pImage->cbCluster = RT_BIT_32(Header.Version.v2.u32ClusterBits); 1195 pImage->cL2TableEntries = pImage->cbCluster / sizeof(uint64_t); 1196 pImage->cbL2Table = pImage->cbCluster; 1197 pImage->offL1Table = Header.Version.v2.u64L1TableOffset; 1198 pImage->cL1TableEntries = Header.Version.v2.u32L1Size; 1199 pImage->offRefcountTable = Header.Version.v2.u64RefcountTableOffset; 1200 pImage->cbRefcountTable = qcowCluster2Byte(pImage, Header.Version.v2.u32RefcountTableClusters); 1201 pImage->cRefcountTableEntries = pImage->cbRefcountTable / sizeof(uint64_t); 1142 /* Load backing filename from image. */ 1143 pImage->pszBackingFilename = (char *)RTMemAllocZ(pImage->cbBackingFilename + 1); /* +1 for \0 terminator. */ 1144 if (pImage->pszBackingFilename) 1145 { 1146 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1147 pImage->offBackingFilename, pImage->pszBackingFilename, 1148 pImage->cbBackingFilename); 1149 } 1150 else 1151 rc = VERR_NO_MEMORY; 1152 } 1153 1154 if ( RT_SUCCESS(rc) 1155 && pImage->cbRefcountTable 1156 && pImage->offRefcountTable) 1157 { 1158 /* Load refcount table. */ 1159 Assert(pImage->cRefcountTableEntries); 1160 pImage->paRefcountTable = (uint64_t *)RTMemAllocZ(pImage->cbRefcountTable); 1161 if (RT_LIKELY(pImage->paRefcountTable)) 1162 { 1163 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1164 pImage->offRefcountTable, pImage->paRefcountTable, 1165 pImage->cbRefcountTable); 1166 if (RT_SUCCESS(rc)) 1167 qcowTableConvertToHostEndianess(pImage->paRefcountTable, 1168 pImage->cRefcountTableEntries); 1169 else 1170 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1171 N_("QCow: Reading refcount table of image '%s' failed"), 1172 pImage->pszFilename); 1173 } 1174 else 1175 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, 1176 N_("QCow: Allocating memory for refcount table of image '%s' failed"), 1177 pImage->pszFilename); 1178 } 1179 1180 if (RT_SUCCESS(rc)) 1181 { 1182 qcowTableMasksInit(pImage); 1183 1184 /* Allocate L1 table. */ 1185 pImage->paL1Table = (uint64_t *)RTMemAllocZ(pImage->cbL1Table); 1186 if (pImage->paL1Table) 1187 { 1188 /* Read from the image. */ 1189 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1190 pImage->offL1Table, pImage->paL1Table, 1191 pImage->cbL1Table); 1192 if (RT_SUCCESS(rc)) 1193 qcowTableConvertToHostEndianess(pImage->paL1Table, pImage->cL1TableEntries); 1194 else 1195 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1196 N_("QCow: Reading the L1 table for image '%s' failed"), 1197 pImage->pszFilename); 1198 } 1199 else 1200 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, 1201 N_("QCow: Out of memory allocating L1 table for image '%s'"), 1202 pImage->pszFilename); 1202 1203 } 1203 1204 } 1204 else 1205 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1206 N_("QCow: Image '%s' uses version %u which is not supported"), 1207 pImage->pszFilename, Header.u32Version); 1208 1209 pImage->cbL1Table = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster); 1210 if ((uint64_t)pImage->cbL1Table != RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster)) 1211 rc = vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS, 1212 N_("QCOW: L1 table size overflow in image '%s'"), 1213 pImage->pszFilename); 1205 else if (RT_SUCCESS(rc)) 1206 rc = VERR_VD_GEN_INVALID_HEADER; 1214 1207 } 1215 1216 /** @todo Check that there are no compressed clusters in the image 1217 * (by traversing the L2 tables and checking each offset). 1218 * Refuse to open such images. 1219 */ 1220 1221 if ( RT_SUCCESS(rc) 1222 && pImage->cbBackingFilename 1223 && pImage->offBackingFilename) 1224 { 1225 /* Load backing filename from image. */ 1226 pImage->pszBackingFilename = (char *)RTMemAllocZ(pImage->cbBackingFilename + 1); /* +1 for \0 terminator. */ 1227 if (pImage->pszBackingFilename) 1228 { 1229 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1230 pImage->offBackingFilename, pImage->pszBackingFilename, 1231 pImage->cbBackingFilename); 1232 } 1233 else 1234 rc = VERR_NO_MEMORY; 1235 } 1236 1237 if ( RT_SUCCESS(rc) 1238 && pImage->cbRefcountTable 1239 && pImage->offRefcountTable) 1240 { 1241 /* Load refcount table. */ 1242 Assert(pImage->cRefcountTableEntries); 1243 pImage->paRefcountTable = (uint64_t *)RTMemAllocZ(pImage->cbRefcountTable); 1244 if (RT_LIKELY(pImage->paRefcountTable)) 1245 { 1246 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1247 pImage->offRefcountTable, pImage->paRefcountTable, 1248 pImage->cbRefcountTable); 1249 if (RT_SUCCESS(rc)) 1250 qcowTableConvertToHostEndianess(pImage->paRefcountTable, 1251 pImage->cRefcountTableEntries); 1252 else 1253 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1254 N_("QCow: Reading refcount table of image '%s' failed"), 1255 pImage->pszFilename); 1256 } 1257 else 1258 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, 1259 N_("QCow: Allocating memory for refcount table of image '%s' failed"), 1260 pImage->pszFilename); 1261 } 1262 1263 if (RT_SUCCESS(rc)) 1264 { 1265 qcowTableMasksInit(pImage); 1266 1267 /* Allocate L1 table. */ 1268 pImage->paL1Table = (uint64_t *)RTMemAllocZ(pImage->cbL1Table); 1269 if (pImage->paL1Table) 1270 { 1271 /* Read from the image. */ 1272 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 1273 pImage->offL1Table, pImage->paL1Table, 1274 pImage->cbL1Table); 1275 if (RT_SUCCESS(rc)) 1276 qcowTableConvertToHostEndianess(pImage->paL1Table, pImage->cL1TableEntries); 1277 else 1278 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1279 N_("QCow: Reading the L1 table for image '%s' failed"), 1280 pImage->pszFilename); 1281 } 1282 else 1283 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, 1284 N_("QCow: Out of memory allocating L1 table for image '%s'"), 1285 pImage->pszFilename); 1286 } 1208 else if (RT_SUCCESS(rc)) 1209 rc = VERR_VD_GEN_INVALID_HEADER; 1287 1210 } 1288 else if (RT_SUCCESS(rc))1289 rc = VERR_VD_GEN_INVALID_HEADER;1211 /* else: Do NOT signal an appropriate error here, as the VD layer has the 1212 * choice of retrying the open if it failed. */ 1290 1213 } 1291 1214 else 1292 rc = VERR_VD_GEN_INVALID_HEADER; 1293 1294 out: 1215 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1216 N_("Qcow: Creating the L2 table cache for image '%s' failed"), 1217 pImage->pszFilename); 1218 1295 1219 if (RT_FAILURE(rc)) 1296 1220 qcowFreeImage(pImage, false); … … 1305 1229 PCVDGEOMETRY pPCHSGeometry, 1306 1230 PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags, 1307 P FNVDPROGRESS pfnProgress, void *pvUser,1231 PVDINTERFACEPROGRESS pIfProgress, 1308 1232 unsigned uPercentStart, unsigned uPercentSpan) 1309 1233 { … … 1312 1236 int32_t fOpen; 1313 1237 1314 if (uImageFlags & VD_IMAGE_FLAGS_FIXED) 1315 { 1238 if (!(uImageFlags & VD_IMAGE_FLAGS_FIXED)) 1239 { 1240 rc = qcowL2TblCacheCreate(pImage); 1241 if (RT_SUCCESS(rc)) 1242 { 1243 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; 1244 pImage->uImageFlags = uImageFlags; 1245 pImage->PCHSGeometry = *pPCHSGeometry; 1246 pImage->LCHSGeometry = *pLCHSGeometry; 1247 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); 1248 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); 1249 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); 1250 1251 /* Create image file. */ 1252 fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */); 1253 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage); 1254 if (RT_SUCCESS(rc)) 1255 { 1256 /* Init image state. */ 1257 pImage->uVersion = 1; /* We create only version 1 images at the moment. */ 1258 pImage->cbSize = cbSize; 1259 pImage->cbCluster = QCOW_CLUSTER_SIZE_DEFAULT; 1260 pImage->cbL2Table = qcowCluster2Byte(pImage, QCOW_L2_CLUSTERS_DEFAULT); 1261 pImage->cL2TableEntries = pImage->cbL2Table / sizeof(uint64_t); 1262 pImage->cL1TableEntries = cbSize / (pImage->cbCluster * pImage->cL2TableEntries); 1263 if (cbSize % (pImage->cbCluster * pImage->cL2TableEntries)) 1264 pImage->cL1TableEntries++; 1265 pImage->cbL1Table = pImage->cL1TableEntries * sizeof(uint64_t); 1266 pImage->offL1Table = QCOW_V1_HDR_SIZE; 1267 pImage->cbBackingFilename = 0; 1268 pImage->offBackingFilename = 0; 1269 pImage->offNextCluster = RT_ALIGN_64(QCOW_V1_HDR_SIZE + pImage->cbL1Table, pImage->cbCluster); 1270 qcowTableMasksInit(pImage); 1271 1272 /* Init L1 table. */ 1273 pImage->paL1Table = (uint64_t *)RTMemAllocZ(pImage->cbL1Table); 1274 if (RT_LIKELY(pImage->paL1Table)) 1275 { 1276 if (RT_SUCCESS(rc)) 1277 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100); 1278 1279 rc = qcowFlushImage(pImage); 1280 if (RT_SUCCESS(rc)) 1281 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->offNextCluster); 1282 } 1283 else 1284 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, N_("QCow: cannot allocate memory for L1 table of image '%s'"), 1285 pImage->pszFilename); 1286 } 1287 else 1288 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("QCow: cannot create image '%s'"), pImage->pszFilename); 1289 } 1290 else 1291 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("QCow: Failed to create L2 cache for image '%s'"), 1292 pImage->pszFilename); 1293 } 1294 else 1316 1295 rc = vdIfError(pImage->pIfError, VERR_VD_INVALID_TYPE, RT_SRC_POS, N_("QCow: cannot create fixed image '%s'"), pImage->pszFilename); 1317 goto out; 1318 } 1319 1320 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; 1321 pImage->uImageFlags = uImageFlags; 1322 pImage->PCHSGeometry = *pPCHSGeometry; 1323 pImage->LCHSGeometry = *pLCHSGeometry; 1324 1325 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); 1326 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); 1327 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); 1328 1329 /* Create image file. */ 1330 fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */); 1331 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage); 1332 if (RT_FAILURE(rc)) 1333 { 1334 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("QCow: cannot create image '%s'"), pImage->pszFilename); 1335 goto out; 1336 } 1337 1338 /* Init image state. */ 1339 pImage->uVersion = 1; /* We create only version 1 images at the moment. */ 1340 pImage->cbSize = cbSize; 1341 pImage->cbCluster = QCOW_CLUSTER_SIZE_DEFAULT; 1342 pImage->cbL2Table = qcowCluster2Byte(pImage, QCOW_L2_CLUSTERS_DEFAULT); 1343 pImage->cL2TableEntries = pImage->cbL2Table / sizeof(uint64_t); 1344 pImage->cL1TableEntries = cbSize / (pImage->cbCluster * pImage->cL2TableEntries); 1345 if (cbSize % (pImage->cbCluster * pImage->cL2TableEntries)) 1346 pImage->cL1TableEntries++; 1347 pImage->cbL1Table = pImage->cL1TableEntries * sizeof(uint64_t); 1348 pImage->offL1Table = QCOW_V1_HDR_SIZE; 1349 pImage->cbBackingFilename = 0; 1350 pImage->offBackingFilename = 0; 1351 pImage->offNextCluster = RT_ALIGN_64(QCOW_V1_HDR_SIZE + pImage->cbL1Table, pImage->cbCluster); 1352 qcowTableMasksInit(pImage); 1353 1354 /* Init L1 table. */ 1355 pImage->paL1Table = (uint64_t *)RTMemAllocZ(pImage->cbL1Table); 1356 if (!pImage->paL1Table) 1357 { 1358 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, N_("QCow: cannot allocate memory for L1 table of image '%s'"), 1359 pImage->pszFilename); 1360 goto out; 1361 } 1362 1363 rc = qcowL2TblCacheCreate(pImage); 1364 if (RT_FAILURE(rc)) 1365 { 1366 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("QCow: Failed to create L2 cache for image '%s'"), 1367 pImage->pszFilename); 1368 goto out; 1369 } 1370 1371 if (RT_SUCCESS(rc) && pfnProgress) 1372 pfnProgress(pvUser, uPercentStart + uPercentSpan * 98 / 100); 1373 1374 rc = qcowFlushImage(pImage); 1296 1375 1297 if (RT_SUCCESS(rc)) 1376 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->offNextCluster); 1377 1378 out: 1379 if (RT_SUCCESS(rc) && pfnProgress) 1380 pfnProgress(pvUser, uPercentStart + uPercentSpan); 1298 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan); 1381 1299 1382 1300 if (RT_FAILURE(rc)) … … 1544 1462 PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage); 1545 1463 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1546 1547 if ( !VALID_PTR(pszFilename) 1548 || !*pszFilename) 1549 { 1550 rc = VERR_INVALID_PARAMETER; 1551 goto out; 1552 } 1464 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER); 1553 1465 1554 1466 /* … … 1570 1482 if ( RT_SUCCESS(rc) 1571 1483 && qcowHdrConvertToHostEndianess(&Header)) 1572 {1573 1484 *penmType = VDTYPE_HDD; 1574 rc = VINF_SUCCESS;1575 }1576 1485 else 1577 1486 rc = VERR_VD_GEN_INVALID_HEADER; … … 1584 1493 vdIfIoIntFileClose(pIfIo, pStorage); 1585 1494 1586 out:1587 1495 LogFlowFunc(("returns %Rrc\n", rc)); 1588 1496 return rc; … … 1594 1502 VDTYPE enmType, void **ppBackendData) 1595 1503 { 1596 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData)); 1504 RT_NOREF1(enmType); /**< @todo r=klaus make use of the type info. */ 1505 1506 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n", 1507 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData)); 1597 1508 int rc; 1598 PQCOWIMAGE pImage;1599 1600 NOREF(enmType); /**< @todo r=klaus make use of the type info. */1601 1509 1602 1510 /* Check open flags. All valid flags are supported. */ 1603 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)1604 {1605 rc = VERR_INVALID_PARAMETER; 1606 goto out;1607 }1608 1609 /* Check remaining arguments. */1610 if ( !VALID_PTR(pszFilename)1611 || !*pszFilename)1612 {1613 rc = VERR_INVALID_PARAMETER; 1614 goto out;1615 }1616 1617 1618 pImage = (PQCOWIMAGE)RTMemAllocZ(sizeof(QCOWIMAGE));1619 if (!pImage)1620 {1511 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER); 1512 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER); 1513 1514 PQCOWIMAGE pImage = (PQCOWIMAGE)RTMemAllocZ(sizeof(QCOWIMAGE)); 1515 if (RT_LIKELY(pImage)) 1516 { 1517 pImage->pszFilename = pszFilename; 1518 pImage->pStorage = NULL; 1519 pImage->pVDIfsDisk = pVDIfsDisk; 1520 pImage->pVDIfsImage = pVDIfsImage; 1521 1522 rc = qcowOpenImage(pImage, uOpenFlags); 1523 if (RT_SUCCESS(rc)) 1524 *ppBackendData = pImage; 1525 else 1526 RTMemFree(pImage); 1527 } 1528 else 1621 1529 rc = VERR_NO_MEMORY; 1622 goto out; 1623 } 1624 pImage->pszFilename = pszFilename; 1625 pImage->pStorage = NULL; 1626 pImage->pVDIfsDisk = pVDIfsDisk; 1627 pImage->pVDIfsImage = pVDIfsImage; 1628 1629 rc = qcowOpenImage(pImage, uOpenFlags); 1630 if (RT_SUCCESS(rc)) 1631 *ppBackendData = pImage; 1632 else 1633 RTMemFree(pImage); 1634 1635 out: 1530 1636 1531 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData)); 1637 1532 return rc; … … 1652 1547 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData)); 1653 1548 int rc; 1654 PQCOWIMAGE pImage;1655 1656 PFNVDPROGRESS pfnProgress = NULL;1657 void *pvUser = NULL;1658 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);1659 if (pIfProgress)1660 {1661 pfnProgress = pIfProgress->pfnProgress;1662 pvUser = pIfProgress->Core.pvUser;1663 }1664 1549 1665 1550 /* Check the VD container type. */ 1666 1551 if (enmType != VDTYPE_HDD) 1667 { 1668 rc = VERR_VD_INVALID_TYPE; 1669 goto out; 1670 } 1552 return VERR_VD_INVALID_TYPE; 1671 1553 1672 1554 /* Check open flags. All valid flags are supported. */ 1673 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 1674 { 1675 rc = VERR_INVALID_PARAMETER; 1676 goto out; 1677 } 1678 1679 /* Check remaining arguments. */ 1680 if ( !VALID_PTR(pszFilename) 1681 || !*pszFilename 1682 || !VALID_PTR(pPCHSGeometry) 1683 || !VALID_PTR(pLCHSGeometry)) 1684 { 1685 rc = VERR_INVALID_PARAMETER; 1686 goto out; 1687 } 1688 1689 pImage = (PQCOWIMAGE)RTMemAllocZ(sizeof(QCOWIMAGE)); 1690 if (!pImage) 1691 { 1555 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER); 1556 AssertReturn( VALID_PTR(pszFilename) 1557 && *pszFilename 1558 && VALID_PTR(pPCHSGeometry) 1559 && VALID_PTR(pLCHSGeometry), VERR_INVALID_PARAMETER); 1560 1561 PQCOWIMAGE pImage = (PQCOWIMAGE)RTMemAllocZ(sizeof(QCOWIMAGE)); 1562 if (RT_LIKELY(pImage)) 1563 { 1564 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation); 1565 1566 pImage->pszFilename = pszFilename; 1567 pImage->pStorage = NULL; 1568 pImage->pVDIfsDisk = pVDIfsDisk; 1569 pImage->pVDIfsImage = pVDIfsImage; 1570 1571 rc = qcowCreateImage(pImage, cbSize, uImageFlags, pszComment, 1572 pPCHSGeometry, pLCHSGeometry, uOpenFlags, 1573 pIfProgress, uPercentStart, uPercentSpan); 1574 if (RT_SUCCESS(rc)) 1575 { 1576 /* So far the image is opened in read/write mode. Make sure the 1577 * image is opened in read-only mode if the caller requested that. */ 1578 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 1579 { 1580 qcowFreeImage(pImage, false); 1581 rc = qcowOpenImage(pImage, uOpenFlags); 1582 } 1583 1584 if (RT_SUCCESS(rc)) 1585 *ppBackendData = pImage; 1586 } 1587 1588 if (RT_FAILURE(rc)) 1589 RTMemFree(pImage); 1590 } 1591 else 1692 1592 rc = VERR_NO_MEMORY; 1693 goto out; 1694 } 1695 pImage->pszFilename = pszFilename; 1696 pImage->pStorage = NULL; 1697 pImage->pVDIfsDisk = pVDIfsDisk; 1698 pImage->pVDIfsImage = pVDIfsImage; 1699 1700 rc = qcowCreateImage(pImage, cbSize, uImageFlags, pszComment, 1701 pPCHSGeometry, pLCHSGeometry, uOpenFlags, 1702 pfnProgress, pvUser, uPercentStart, uPercentSpan); 1703 if (RT_SUCCESS(rc)) 1704 { 1705 /* So far the image is opened in read/write mode. Make sure the 1706 * image is opened in read-only mode if the caller requested that. */ 1707 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 1708 { 1709 qcowFreeImage(pImage, false); 1710 rc = qcowOpenImage(pImage, uOpenFlags); 1711 if (RT_FAILURE(rc)) 1712 { 1713 RTMemFree(pImage); 1714 goto out; 1715 } 1716 } 1717 *ppBackendData = pImage; 1718 } 1719 else 1720 RTMemFree(pImage); 1721 1722 out: 1593 1723 1594 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData)); 1724 1595 return rc; … … 1733 1604 1734 1605 /* Check arguments. */ 1735 if ( !pImage 1736 || !pszFilename 1737 || !*pszFilename) 1738 { 1739 rc = VERR_INVALID_PARAMETER; 1740 goto out; 1741 } 1606 AssertReturn((pImage && pszFilename && *pszFilename), VERR_INVALID_PARAMETER); 1742 1607 1743 1608 /* Close the image. */ 1744 1609 rc = qcowFreeImage(pImage, false); 1745 if (RT_FAILURE(rc)) 1746 goto out; 1747 1748 /* Rename the file. */ 1749 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0); 1750 if (RT_FAILURE(rc)) 1751 { 1752 /* The move failed, try to reopen the original image. */ 1753 int rc2 = qcowOpenImage(pImage, pImage->uOpenFlags); 1754 if (RT_FAILURE(rc2)) 1755 rc = rc2; 1756 1757 goto out; 1758 } 1759 1760 /* Update pImage with the new information. */ 1761 pImage->pszFilename = pszFilename; 1762 1763 /* Open the old image with new name. */ 1764 rc = qcowOpenImage(pImage, pImage->uOpenFlags); 1765 if (RT_FAILURE(rc)) 1766 goto out; 1767 1768 out: 1610 if (RT_SUCCESS(rc)) 1611 { 1612 /* Rename the file. */ 1613 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0); 1614 if (RT_SUCCESS(rc)) 1615 { 1616 /* Update pImage with the new information. */ 1617 pImage->pszFilename = pszFilename; 1618 1619 /* Open the old image with new name. */ 1620 rc = qcowOpenImage(pImage, pImage->uOpenFlags); 1621 } 1622 else 1623 { 1624 /* The move failed, try to reopen the original image. */ 1625 int rc2 = qcowOpenImage(pImage, pImage->uOpenFlags); 1626 if (RT_FAILURE(rc2)) 1627 rc = rc2; 1628 } 1629 } 1630 1769 1631 LogFlowFunc(("returns %Rrc\n", rc)); 1770 1632 return rc; … … 1776 1638 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 1777 1639 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1778 int rc; 1779 1780 rc = qcowFreeImage(pImage, fDelete); 1640 1641 int rc = qcowFreeImage(pImage, fDelete); 1781 1642 RTMemFree(pImage); 1782 1643 … … 1800 1661 Assert(uOffset % 512 == 0); 1801 1662 Assert(cbToRead % 512 == 0); 1802 1803 if (!VALID_PTR(pIoCtx) || !cbToRead) 1804 { 1805 rc = VERR_INVALID_PARAMETER; 1806 goto out; 1807 } 1808 1809 if ( uOffset + cbToRead > pImage->cbSize 1810 || cbToRead == 0) 1811 { 1812 rc = VERR_INVALID_PARAMETER; 1813 goto out; 1814 } 1663 AssertReturn((VALID_PTR(pIoCtx) && cbToRead), VERR_INVALID_PARAMETER); 1664 AssertReturn(uOffset + cbToRead <= pImage->cbSize, VERR_INVALID_PARAMETER); 1815 1665 1816 1666 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); … … 1831 1681 *pcbActuallyRead = cbToRead; 1832 1682 1833 out:1834 1683 LogFlowFunc(("returns %Rrc\n", rc)); 1835 1684 return rc; … … 1852 1701 Assert(!(uOffset % 512)); 1853 1702 Assert(!(cbToWrite % 512)); 1854 1855 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1856 { 1857 rc = VERR_VD_IMAGE_READ_ONLY; 1858 goto out; 1859 } 1860 1861 if (!VALID_PTR(pIoCtx) || !cbToWrite) 1862 { 1863 rc = VERR_INVALID_PARAMETER; 1864 goto out; 1865 } 1866 1867 if ( uOffset + cbToWrite > pImage->cbSize 1868 || cbToWrite == 0) 1869 { 1870 rc = VERR_INVALID_PARAMETER; 1871 goto out; 1872 } 1873 1874 /* Convert offset to L1, L2 index and cluster offset. */ 1875 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 1876 1877 /* Clip write size to remain in the cluster. */ 1878 cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster); 1879 Assert(!(cbToWrite % 512)); 1880 1881 /* Get offset in image. */ 1882 rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage); 1883 if (RT_SUCCESS(rc)) 1884 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, 1885 offImage, pIoCtx, cbToWrite, NULL, NULL); 1886 else if (rc == VERR_VD_BLOCK_FREE) 1887 { 1888 if ( cbToWrite == pImage->cbCluster 1889 && !(fWrite & VD_WRITE_NO_ALLOC)) 1890 { 1891 PQCOWL2CACHEENTRY pL2Entry = NULL; 1892 1893 /* Full cluster write to previously unallocated cluster. 1894 * Allocate cluster and write data. */ 1895 Assert(!offCluster); 1896 1897 do 1703 AssertReturn((VALID_PTR(pIoCtx) && cbToWrite), VERR_INVALID_PARAMETER); 1704 AssertReturn(uOffset + cbToWrite <= pImage->cbSize, VERR_INVALID_PARAMETER); 1705 1706 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1707 { 1708 /* Convert offset to L1, L2 index and cluster offset. */ 1709 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster); 1710 1711 /* Clip write size to remain in the cluster. */ 1712 cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster); 1713 Assert(!(cbToWrite % 512)); 1714 1715 /* Get offset in image. */ 1716 rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage); 1717 if (RT_SUCCESS(rc)) 1718 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, 1719 offImage, pIoCtx, cbToWrite, NULL, NULL); 1720 else if (rc == VERR_VD_BLOCK_FREE) 1721 { 1722 if ( cbToWrite == pImage->cbCluster 1723 && !(fWrite & VD_WRITE_NO_ALLOC)) 1898 1724 { 1899 /* Check if we have to allocate a new cluster for L2 tables. */ 1900 if (!pImage->paL1Table[idxL1]) 1725 PQCOWL2CACHEENTRY pL2Entry = NULL; 1726 1727 /* Full cluster write to previously unallocated cluster. 1728 * Allocate cluster and write data. */ 1729 Assert(!offCluster); 1730 1731 do 1901 1732 { 1902 uint64_t offL2Tbl; 1903 PQCOWCLUSTERASYNCALLOC pL2ClusterAlloc = NULL; 1904 1905 /* Allocate new async cluster allocation state. */ 1906 pL2ClusterAlloc = (PQCOWCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QCOWCLUSTERASYNCALLOC)); 1907 if (RT_UNLIKELY(!pL2ClusterAlloc)) 1733 /* Check if we have to allocate a new cluster for L2 tables. */ 1734 if (!pImage->paL1Table[idxL1]) 1908 1735 { 1909 rc = VERR_NO_MEMORY; 1910 break; 1911 } 1912 1913 pL2Entry = qcowL2TblCacheEntryAlloc(pImage); 1914 if (!pL2Entry) 1915 { 1916 rc = VERR_NO_MEMORY; 1917 RTMemFree(pL2ClusterAlloc); 1918 break; 1919 } 1920 1921 offL2Tbl = qcowClusterAllocate(pImage, qcowByte2Cluster(pImage, pImage->cbL2Table)); 1922 pL2Entry->offL2Tbl = offL2Tbl; 1923 memset(pL2Entry->paL2Tbl, 0, pImage->cbL2Table); 1924 1925 pL2ClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_L2_ALLOC; 1926 pL2ClusterAlloc->offNextClusterOld = offL2Tbl; 1927 pL2ClusterAlloc->offClusterNew = offL2Tbl; 1928 pL2ClusterAlloc->idxL1 = idxL1; 1929 pL2ClusterAlloc->idxL2 = idxL2; 1930 pL2ClusterAlloc->cbToWrite = cbToWrite; 1931 pL2ClusterAlloc->pL2Entry = pL2Entry; 1932 1933 /* 1934 * Write the L2 table first and link to the L1 table afterwards. 1935 * If something unexpected happens the worst case which can happen 1936 * is a leak of some clusters. 1937 */ 1938 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, 1939 offL2Tbl, pL2Entry->paL2Tbl, pImage->cbL2Table, pIoCtx, 1940 qcowAsyncClusterAllocUpdate, pL2ClusterAlloc); 1941 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1942 break; 1943 else if (RT_FAILURE(rc)) 1944 { 1945 RTMemFree(pL2ClusterAlloc); 1946 qcowL2TblCacheEntryFree(pImage, pL2Entry); 1947 break; 1948 } 1949 1950 rc = qcowAsyncClusterAllocUpdate(pImage, pIoCtx, pL2ClusterAlloc, rc); 1951 } 1952 else 1953 { 1954 rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1], 1955 &pL2Entry); 1956 if (RT_SUCCESS(rc)) 1957 { 1958 PQCOWCLUSTERASYNCALLOC pDataClusterAlloc = NULL; 1736 uint64_t offL2Tbl; 1737 PQCOWCLUSTERASYNCALLOC pL2ClusterAlloc = NULL; 1959 1738 1960 1739 /* Allocate new async cluster allocation state. */ 1961 p DataClusterAlloc = (PQCOWCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QCOWCLUSTERASYNCALLOC));1962 if (RT_UNLIKELY(!p DataClusterAlloc))1740 pL2ClusterAlloc = (PQCOWCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QCOWCLUSTERASYNCALLOC)); 1741 if (RT_UNLIKELY(!pL2ClusterAlloc)) 1963 1742 { 1964 1743 rc = VERR_NO_MEMORY; … … 1966 1745 } 1967 1746 1968 /* Allocate new cluster for the data. */ 1969 uint64_t offData = qcowClusterAllocate(pImage, 1); 1970 1971 pDataClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC; 1972 pDataClusterAlloc->offNextClusterOld = offData; 1973 pDataClusterAlloc->offClusterNew = offData; 1974 pDataClusterAlloc->idxL1 = idxL1; 1975 pDataClusterAlloc->idxL2 = idxL2; 1976 pDataClusterAlloc->cbToWrite = cbToWrite; 1977 pDataClusterAlloc->pL2Entry = pL2Entry; 1978 1979 /* Write data. */ 1980 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, 1981 offData, pIoCtx, cbToWrite, 1982 qcowAsyncClusterAllocUpdate, pDataClusterAlloc); 1747 pL2Entry = qcowL2TblCacheEntryAlloc(pImage); 1748 if (!pL2Entry) 1749 { 1750 rc = VERR_NO_MEMORY; 1751 RTMemFree(pL2ClusterAlloc); 1752 break; 1753 } 1754 1755 offL2Tbl = qcowClusterAllocate(pImage, qcowByte2Cluster(pImage, pImage->cbL2Table)); 1756 pL2Entry->offL2Tbl = offL2Tbl; 1757 memset(pL2Entry->paL2Tbl, 0, pImage->cbL2Table); 1758 1759 pL2ClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_L2_ALLOC; 1760 pL2ClusterAlloc->offNextClusterOld = offL2Tbl; 1761 pL2ClusterAlloc->offClusterNew = offL2Tbl; 1762 pL2ClusterAlloc->idxL1 = idxL1; 1763 pL2ClusterAlloc->idxL2 = idxL2; 1764 pL2ClusterAlloc->cbToWrite = cbToWrite; 1765 pL2ClusterAlloc->pL2Entry = pL2Entry; 1766 1767 /* 1768 * Write the L2 table first and link to the L1 table afterwards. 1769 * If something unexpected happens the worst case which can happen 1770 * is a leak of some clusters. 1771 */ 1772 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, 1773 offL2Tbl, pL2Entry->paL2Tbl, pImage->cbL2Table, pIoCtx, 1774 qcowAsyncClusterAllocUpdate, pL2ClusterAlloc); 1983 1775 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1984 1776 break; 1985 1777 else if (RT_FAILURE(rc)) 1986 1778 { 1987 RTMemFree(pDataClusterAlloc); 1779 RTMemFree(pL2ClusterAlloc); 1780 qcowL2TblCacheEntryFree(pImage, pL2Entry); 1988 1781 break; 1989 1782 } 1990 1783 1991 rc = qcowAsyncClusterAllocUpdate(pImage, pIoCtx, p DataClusterAlloc, rc);1784 rc = qcowAsyncClusterAllocUpdate(pImage, pIoCtx, pL2ClusterAlloc, rc); 1992 1785 } 1993 } 1994 1995 } while (0); 1996 1997 *pcbPreRead = 0; 1998 *pcbPostRead = 0; 1786 else 1787 { 1788 rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1], 1789 &pL2Entry); 1790 if (RT_SUCCESS(rc)) 1791 { 1792 PQCOWCLUSTERASYNCALLOC pDataClusterAlloc = NULL; 1793 1794 /* Allocate new async cluster allocation state. */ 1795 pDataClusterAlloc = (PQCOWCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QCOWCLUSTERASYNCALLOC)); 1796 if (RT_UNLIKELY(!pDataClusterAlloc)) 1797 { 1798 rc = VERR_NO_MEMORY; 1799 break; 1800 } 1801 1802 /* Allocate new cluster for the data. */ 1803 uint64_t offData = qcowClusterAllocate(pImage, 1); 1804 1805 pDataClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC; 1806 pDataClusterAlloc->offNextClusterOld = offData; 1807 pDataClusterAlloc->offClusterNew = offData; 1808 pDataClusterAlloc->idxL1 = idxL1; 1809 pDataClusterAlloc->idxL2 = idxL2; 1810 pDataClusterAlloc->cbToWrite = cbToWrite; 1811 pDataClusterAlloc->pL2Entry = pL2Entry; 1812 1813 /* Write data. */ 1814 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, 1815 offData, pIoCtx, cbToWrite, 1816 qcowAsyncClusterAllocUpdate, pDataClusterAlloc); 1817 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1818 break; 1819 else if (RT_FAILURE(rc)) 1820 { 1821 RTMemFree(pDataClusterAlloc); 1822 break; 1823 } 1824 1825 rc = qcowAsyncClusterAllocUpdate(pImage, pIoCtx, pDataClusterAlloc, rc); 1826 } 1827 } 1828 1829 } while (0); 1830 1831 *pcbPreRead = 0; 1832 *pcbPostRead = 0; 1833 } 1834 else 1835 { 1836 /* Trying to do a partial write to an unallocated cluster. Don't do 1837 * anything except letting the upper layer know what to do. */ 1838 *pcbPreRead = offCluster; 1839 *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead; 1840 } 1999 1841 } 2000 else 2001 { 2002 /* Trying to do a partial write to an unallocated cluster. Don't do 2003 * anything except letting the upper layer know what to do. */ 2004 *pcbPreRead = offCluster; 2005 *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead; 1842 1843 if (pcbWriteProcess) 1844 *pcbWriteProcess = cbToWrite; 1845 } 1846 else 1847 rc = VERR_VD_IMAGE_READ_ONLY; 1848 1849 LogFlowFunc(("returns %Rrc\n", rc)); 1850 return rc; 1851 } 1852 1853 static DECLCALLBACK(int) qcowFlush(void *pBackendData, PVDIOCTX pIoCtx) 1854 { 1855 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1856 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1857 int rc = VINF_SUCCESS; 1858 1859 AssertPtr(pImage); 1860 AssertPtrReturn(pIoCtx, VERR_INVALID_PARAMETER); 1861 1862 if ( pImage->pStorage 1863 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1864 { 1865 QCowHeader Header; 1866 1867 rc = qcowTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table, 1868 pImage->cbL1Table, pImage->cL1TableEntries, NULL, NULL); 1869 if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1870 { 1871 /* Write header. */ 1872 size_t cbHeader = 0; 1873 qcowHdrConvertFromHostEndianess(pImage, &Header, &cbHeader); 1874 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, 1875 0, &Header, cbHeader, 1876 pIoCtx, NULL, NULL); 1877 if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1878 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, 1879 pIoCtx, NULL, NULL); 2006 1880 } 2007 1881 } 2008 2009 if (pcbWriteProcess)2010 *pcbWriteProcess = cbToWrite;2011 2012 2013 out:2014 LogFlowFunc(("returns %Rrc\n", rc));2015 return rc;2016 }2017 2018 static DECLCALLBACK(int) qcowFlush(void *pBackendData, PVDIOCTX pIoCtx)2019 {2020 LogFlowFunc(("pBackendData=%#p\n", pBackendData));2021 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;2022 int rc = VINF_SUCCESS;2023 2024 Assert(pImage);2025 2026 if (VALID_PTR(pIoCtx))2027 rc = qcowFlushImageAsync(pImage, pIoCtx);2028 else2029 rc = VERR_INVALID_PARAMETER;2030 1882 2031 1883 LogFlowFunc(("returns %Rrc\n", rc)); … … 2039 1891 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2040 1892 2041 AssertPtr(pImage); 2042 2043 if (pImage) 2044 return pImage->uVersion; 2045 else 2046 return 0; 1893 AssertPtrReturn(pImage, 0); 1894 1895 return pImage->uVersion; 2047 1896 } 2048 1897 … … 2054 1903 uint32_t cb = 0; 2055 1904 2056 AssertPtr (pImage);2057 2058 if (pImage && pImage->pStorage)1905 AssertPtrReturn(pImage, 0); 1906 1907 if (pImage->pStorage) 2059 1908 cb = 512; 2060 1909 … … 2070 1919 uint64_t cb = 0; 2071 1920 2072 AssertPtr (pImage);2073 2074 if (pImage && pImage->pStorage)1921 AssertPtrReturn(pImage, 0); 1922 1923 if (pImage->pStorage) 2075 1924 cb = pImage->cbSize; 2076 1925 … … 2086 1935 uint64_t cb = 0; 2087 1936 2088 AssertPtr(pImage); 2089 2090 if (pImage) 2091 { 2092 uint64_t cbFile; 2093 if (pImage->pStorage) 2094 { 2095 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 2096 if (RT_SUCCESS(rc)) 2097 cb += cbFile; 2098 } 1937 AssertPtrReturn(pImage, 0); 1938 1939 uint64_t cbFile; 1940 if (pImage->pStorage) 1941 { 1942 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile); 1943 if (RT_SUCCESS(rc)) 1944 cb += cbFile; 2099 1945 } 2100 1946 … … 2104 1950 2105 1951 /** @copydoc VDIMAGEBACKEND::pfnGetPCHSGeometry */ 2106 static DECLCALLBACK(int) qcowGetPCHSGeometry(void *pBackendData, 2107 PVDGEOMETRY pPCHSGeometry) 1952 static DECLCALLBACK(int) qcowGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 2108 1953 { 2109 1954 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 2110 1955 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2111 int rc; 2112 2113 AssertPtr(pImage); 2114 2115 if (pImage) 2116 { 2117 if (pImage->PCHSGeometry.cCylinders) 2118 { 2119 *pPCHSGeometry = pImage->PCHSGeometry; 2120 rc = VINF_SUCCESS; 2121 } 2122 else 2123 rc = VERR_VD_GEOMETRY_NOT_SET; 2124 } 1956 int rc = VINF_SUCCESS; 1957 1958 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 1959 1960 if (pImage->PCHSGeometry.cCylinders) 1961 *pPCHSGeometry = pImage->PCHSGeometry; 2125 1962 else 2126 rc = VERR_VD_ NOT_OPENED;1963 rc = VERR_VD_GEOMETRY_NOT_SET; 2127 1964 2128 1965 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); … … 2131 1968 2132 1969 /** @copydoc VDIMAGEBACKEND::pfnSetPCHSGeometry */ 2133 static DECLCALLBACK(int) qcowSetPCHSGeometry(void *pBackendData, 2134 PCVDGEOMETRY pPCHSGeometry) 2135 { 2136 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 2137 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2138 int rc; 2139 2140 AssertPtr(pImage); 2141 2142 if (pImage) 2143 { 2144 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2145 { 2146 rc = VERR_VD_IMAGE_READ_ONLY; 2147 goto out; 2148 } 2149 1970 static DECLCALLBACK(int) qcowSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 1971 { 1972 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", 1973 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1974 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1975 int rc = VINF_SUCCESS; 1976 1977 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 1978 1979 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1980 rc = VERR_VD_IMAGE_READ_ONLY; 1981 else 2150 1982 pImage->PCHSGeometry = *pPCHSGeometry; 2151 rc = VINF_SUCCESS; 2152 } 1983 1984 LogFlowFunc(("returns %Rrc\n", rc)); 1985 return rc; 1986 } 1987 1988 /** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */ 1989 static DECLCALLBACK(int) qcowGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 1990 { 1991 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 1992 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 1993 int rc = VINF_SUCCESS; 1994 1995 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 1996 1997 if (pImage->LCHSGeometry.cCylinders) 1998 *pLCHSGeometry = pImage->LCHSGeometry; 2153 1999 else 2154 rc = VERR_VD_NOT_OPENED; 2155 2156 out: 2157 LogFlowFunc(("returns %Rrc\n", rc)); 2158 return rc; 2159 } 2160 2161 /** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */ 2162 static DECLCALLBACK(int) qcowGetLCHSGeometry(void *pBackendData, 2163 PVDGEOMETRY pLCHSGeometry) 2164 { 2165 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 2166 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2167 int rc; 2168 2169 AssertPtr(pImage); 2170 2171 if (pImage) 2172 { 2173 if (pImage->LCHSGeometry.cCylinders) 2174 { 2175 *pLCHSGeometry = pImage->LCHSGeometry; 2176 rc = VINF_SUCCESS; 2177 } 2178 else 2179 rc = VERR_VD_GEOMETRY_NOT_SET; 2180 } 2000 rc = VERR_VD_GEOMETRY_NOT_SET; 2001 2002 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, 2003 pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2004 return rc; 2005 } 2006 2007 /** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */ 2008 static DECLCALLBACK(int) qcowSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 2009 { 2010 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, 2011 pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2012 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2013 int rc = VINF_SUCCESS; 2014 2015 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2016 2017 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2018 rc = VERR_VD_IMAGE_READ_ONLY; 2181 2019 else 2182 rc = VERR_VD_NOT_OPENED;2183 2184 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));2185 return rc;2186 }2187 2188 /** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */2189 static DECLCALLBACK(int) qcowSetLCHSGeometry(void *pBackendData,2190 PCVDGEOMETRY pLCHSGeometry)2191 {2192 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));2193 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;2194 int rc;2195 2196 AssertPtr(pImage);2197 2198 if (pImage)2199 {2200 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)2201 {2202 rc = VERR_VD_IMAGE_READ_ONLY;2203 goto out;2204 }2205 2206 2020 pImage->LCHSGeometry = *pLCHSGeometry; 2207 rc = VINF_SUCCESS; 2208 } 2209 else 2210 rc = VERR_VD_NOT_OPENED; 2211 2212 out: 2021 2213 2022 LogFlowFunc(("returns %Rrc\n", rc)); 2214 2023 return rc; … … 2220 2029 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2221 2030 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2222 unsigned uImageFlags; 2223 2224 AssertPtr(pImage); 2225 2226 if (pImage) 2227 uImageFlags = pImage->uImageFlags; 2228 else 2229 uImageFlags = 0; 2230 2231 LogFlowFunc(("returns %#x\n", uImageFlags)); 2232 return uImageFlags; 2031 2032 AssertPtrReturn(pImage, 0); 2033 2034 LogFlowFunc(("returns %#x\n", pImage->uImageFlags)); 2035 return pImage->uImageFlags; 2233 2036 } 2234 2037 … … 2238 2041 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2239 2042 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2240 unsigned uOpenFlags; 2241 2242 AssertPtr(pImage); 2243 2244 if (pImage) 2245 uOpenFlags = pImage->uOpenFlags; 2246 else 2247 uOpenFlags = 0; 2248 2249 LogFlowFunc(("returns %#x\n", uOpenFlags)); 2250 return uOpenFlags; 2043 2044 AssertPtrReturn(pImage, 0); 2045 2046 LogFlowFunc(("returns %#x\n", pImage->uOpenFlags)); 2047 return pImage->uOpenFlags; 2251 2048 } 2252 2049 … … 2256 2053 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2257 2054 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2258 int rc ;2055 int rc = VINF_SUCCESS; 2259 2056 2260 2057 /* Image must be opened and the new flags must be valid. */ 2261 2058 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO 2262 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_S KIP_CONSISTENCY_CHECKS)))2263 {2059 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE 2060 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 2264 2061 rc = VERR_INVALID_PARAMETER; 2265 goto out; 2266 } 2267 2268 /* Implement this operation via reopening the image. */ 2269 rc = qcowFreeImage(pImage, false); 2270 if (RT_FAILURE(rc)) 2271 goto out; 2272 rc = qcowOpenImage(pImage, uOpenFlags); 2273 2274 out: 2062 else 2063 { 2064 /* Implement this operation via reopening the image. */ 2065 rc = qcowFreeImage(pImage, false); 2066 if (RT_SUCCESS(rc)) 2067 rc = qcowOpenImage(pImage, uOpenFlags); 2068 } 2069 2275 2070 LogFlowFunc(("returns %Rrc\n", rc)); 2276 2071 return rc; … … 2283 2078 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2284 2079 PQCOWIMAGE pImage = (PQCOWIMAGE)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 comment='%s'\n", rc, pszComment)); 2295 return rc; 2080 2081 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2082 2083 LogFlowFunc(("returns %Rrc comment='%s'\n", VERR_NOT_SUPPORTED, pszComment)); 2084 return VERR_NOT_SUPPORTED; 2296 2085 } 2297 2086 … … 2302 2091 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2303 2092 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2093 2094 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2095 2304 2096 int rc; 2305 2306 AssertPtr(pImage); 2307 2308 if (pImage) 2309 { 2310 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2311 rc = VERR_VD_IMAGE_READ_ONLY; 2312 else 2313 rc = VERR_NOT_SUPPORTED; 2314 } 2097 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2098 rc = VERR_VD_IMAGE_READ_ONLY; 2315 2099 else 2316 rc = VERR_ VD_NOT_OPENED;2100 rc = VERR_NOT_SUPPORTED; 2317 2101 2318 2102 LogFlowFunc(("returns %Rrc\n", rc)); … … 2326 2110 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2327 2111 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2328 int rc; 2329 2330 AssertPtr(pImage); 2331 2332 if (pImage) 2333 rc = VERR_NOT_SUPPORTED; 2334 else 2335 rc = VERR_VD_NOT_OPENED; 2336 2337 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2338 return rc; 2112 2113 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2114 2115 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid)); 2116 return VERR_NOT_SUPPORTED; 2339 2117 } 2340 2118 … … 2345 2123 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2346 2124 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2125 2126 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2127 2347 2128 int rc; 2348 2349 LogFlowFunc(("%RTuuid\n", pUuid)); 2350 AssertPtr(pImage); 2351 2352 if (pImage) 2353 { 2354 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2355 rc = VERR_NOT_SUPPORTED; 2356 else 2357 rc = VERR_VD_IMAGE_READ_ONLY; 2358 } 2129 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2130 rc = VERR_VD_IMAGE_READ_ONLY; 2359 2131 else 2360 rc = VERR_ VD_NOT_OPENED;2132 rc = VERR_NOT_SUPPORTED; 2361 2133 2362 2134 LogFlowFunc(("returns %Rrc\n", rc)); … … 2370 2142 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2371 2143 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2372 int rc; 2373 2374 AssertPtr(pImage); 2375 2376 if (pImage) 2377 rc = VERR_NOT_SUPPORTED; 2378 else 2379 rc = VERR_VD_NOT_OPENED; 2380 2381 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2382 return rc; 2144 2145 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2146 2147 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid)); 2148 return VERR_NOT_SUPPORTED; 2383 2149 } 2384 2150 … … 2389 2155 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2390 2156 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2157 2158 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2159 2391 2160 int rc; 2392 2393 AssertPtr(pImage); 2394 2395 if (pImage) 2396 { 2397 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2398 rc = VERR_NOT_SUPPORTED; 2399 else 2400 rc = VERR_VD_IMAGE_READ_ONLY; 2401 } 2161 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2162 rc = VERR_VD_IMAGE_READ_ONLY; 2402 2163 else 2403 rc = VERR_ VD_NOT_OPENED;2164 rc = VERR_NOT_SUPPORTED; 2404 2165 2405 2166 LogFlowFunc(("returns %Rrc\n", rc)); … … 2413 2174 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2414 2175 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2415 int rc; 2416 2417 AssertPtr(pImage); 2418 2419 if (pImage) 2420 rc = VERR_NOT_SUPPORTED; 2421 else 2422 rc = VERR_VD_NOT_OPENED; 2423 2424 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2425 return rc; 2176 2177 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2178 2179 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid)); 2180 return VERR_NOT_SUPPORTED; 2426 2181 } 2427 2182 … … 2432 2187 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2433 2188 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2189 2190 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2191 2434 2192 int rc; 2435 2436 AssertPtr(pImage); 2437 2438 if (pImage) 2439 { 2440 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2441 rc = VERR_NOT_SUPPORTED; 2442 else 2443 rc = VERR_VD_IMAGE_READ_ONLY; 2444 } 2193 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2194 rc = VERR_VD_IMAGE_READ_ONLY; 2445 2195 else 2446 rc = VERR_ VD_NOT_OPENED;2196 rc = VERR_NOT_SUPPORTED; 2447 2197 2448 2198 LogFlowFunc(("returns %Rrc\n", rc)); … … 2456 2206 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2457 2207 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2458 int rc; 2459 2460 AssertPtr(pImage); 2461 2462 if (pImage) 2463 rc = VERR_NOT_SUPPORTED; 2464 else 2465 rc = VERR_VD_NOT_OPENED; 2466 2467 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2468 return rc; 2208 2209 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2210 2211 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid)); 2212 return VERR_NOT_SUPPORTED; 2469 2213 } 2470 2214 … … 2475 2219 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2476 2220 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2221 2222 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2223 2477 2224 int rc; 2478 2479 AssertPtr(pImage); 2480 2481 if (pImage) 2482 { 2483 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2484 rc = VERR_NOT_SUPPORTED; 2485 else 2486 rc = VERR_VD_IMAGE_READ_ONLY; 2487 } 2225 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2226 rc = VERR_VD_IMAGE_READ_ONLY; 2488 2227 else 2489 rc = VERR_ VD_NOT_OPENED;2228 rc = VERR_NOT_SUPPORTED; 2490 2229 2491 2230 LogFlowFunc(("returns %Rrc\n", rc)); … … 2498 2237 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData; 2499 2238 2500 AssertPtr(pImage); 2501 if (pImage) 2502 { 2503 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cSector=%llu\n", 2504 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2505 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2506 pImage->cbSize / 512); 2507 } 2239 AssertPtrReturnVoid(pImage); 2240 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 2241 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2242 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2243 pImage->cbSize / 512); 2508 2244 } 2509 2245
Note:
See TracChangeset
for help on using the changeset viewer.