Changeset 40240 in vbox
- Timestamp:
- Feb 23, 2012 8:51:34 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 76450
- Location:
- trunk/src/VBox/Storage
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VDI.cpp
r40033 r40240 3102 3102 if (pcbActuallyDiscarded) 3103 3103 *pcbActuallyDiscarded = cbDiscard; 3104 3105 LogFlowFunc(("returns %Rrc\n", rc)); 3106 return rc; 3107 } 3108 3109 /** @copydoc VBOXHDDBACKEND::pfnRepair */ 3110 static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 3111 PVDINTERFACE pVDIfsImage, uint32_t fFlags) 3112 { 3113 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 3114 int rc; 3115 PVDINTERFACEERROR pIfError; 3116 PVDINTERFACEIOINT pIfIo; 3117 PVDIOSTORAGE pStorage; 3118 uint64_t cbFile; 3119 PVDIIMAGEBLOCKPOINTER paBlocks = NULL; 3120 uint32_t *pu32BlockBitmap = NULL; 3121 VDIPREHEADER PreHdr; 3122 VDIHEADER Hdr; 3123 3124 pIfIo = VDIfIoIntGet(pVDIfsImage); 3125 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 3126 3127 pIfError = VDIfErrorGet(pVDIfsDisk); 3128 3129 do 3130 { 3131 bool fRepairHdr = false; 3132 bool fRepairBlockArray = false; 3133 3134 rc = vdIfIoIntFileOpen(pIfIo, pszFilename, 3135 VDOpenFlagsToFileOpenFlags( fFlags & VD_REPAIR_DRY_RUN 3136 ? VD_OPEN_FLAGS_READONLY 3137 : 0, 3138 false /* fCreate */), 3139 &pStorage); 3140 if (RT_FAILURE(rc)) 3141 { 3142 rc = vdIfError(pIfError, rc, RT_SRC_POS, "VDI: Failed to open image \"%s\"", pszFilename); 3143 break; 3144 } 3145 3146 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile); 3147 if (RT_FAILURE(rc)) 3148 { 3149 rc = vdIfError(pIfError, rc, RT_SRC_POS, "VDI: Failed to query image size"); 3150 break; 3151 } 3152 3153 /* Read pre-header. */ 3154 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &PreHdr, sizeof(PreHdr), NULL); 3155 if (RT_FAILURE(rc)) 3156 { 3157 rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: Error reading pre-header in '%s'"), pszFilename); 3158 break; 3159 } 3160 rc = vdiValidatePreHeader(&PreHdr); 3161 if (RT_FAILURE(rc)) 3162 { 3163 rc = vdIfError(pIfError, VERR_VD_IMAGE_REPAIR_IMPOSSIBLE, RT_SRC_POS, 3164 N_("VDI: invalid pre-header in '%s'"), pszFilename); 3165 break; 3166 } 3167 3168 /* Read header. */ 3169 Hdr.uVersion = RT_H2LE_U32(PreHdr.u32Version); 3170 switch (GET_MAJOR_HEADER_VERSION(&Hdr)) 3171 { 3172 case 0: 3173 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, sizeof(PreHdr), 3174 &Hdr.u.v0, sizeof(Hdr.u.v0), 3175 NULL); 3176 if (RT_FAILURE(rc)) 3177 rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v0 header in '%s'"), 3178 pszFilename); 3179 break; 3180 case 1: 3181 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, sizeof(PreHdr), 3182 &Hdr.u.v1, sizeof(Hdr.u.v1), NULL); 3183 if (RT_FAILURE(rc)) 3184 { 3185 rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v1 header in '%s'"), 3186 pszFilename); 3187 } 3188 if (Hdr.u.v1.cbHeader >= sizeof(Hdr.u.v1plus)) 3189 { 3190 /* Read the VDI 1.1+ header completely. */ 3191 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, sizeof(PreHdr), 3192 &Hdr.u.v1plus, sizeof(Hdr.u.v1plus), 3193 NULL); 3194 if (RT_FAILURE(rc)) 3195 rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v1.1+ header in '%s'"), 3196 pszFilename); 3197 } 3198 break; 3199 default: 3200 rc = vdIfError(pIfError, VERR_VD_IMAGE_REPAIR_IMPOSSIBLE, RT_SRC_POS, 3201 N_("VDI: unsupported major version %u in '%s'"), 3202 GET_MAJOR_HEADER_VERSION(&Hdr), pszFilename); 3203 break; 3204 } 3205 3206 if (RT_SUCCESS(rc)) 3207 { 3208 rc = vdiValidateHeader(&Hdr); 3209 if (RT_FAILURE(rc)) 3210 { 3211 rc = vdIfError(pIfError, VERR_VD_IMAGE_REPAIR_IMPOSSIBLE, RT_SRC_POS, 3212 N_("VDI: invalid header in '%s'"), pszFilename); 3213 break; 3214 } 3215 } 3216 3217 /* Setup image parameters by header. */ 3218 uint64_t offStartBlocks, offStartData; 3219 size_t cbTotalBlockData; 3220 3221 offStartBlocks = getImageBlocksOffset(&Hdr); 3222 offStartData = getImageDataOffset(&Hdr); 3223 cbTotalBlockData = getImageExtraBlockSize(&Hdr) + getImageBlockSize(&Hdr); 3224 3225 /* Allocate memory for blocks array. */ 3226 paBlocks = (PVDIIMAGEBLOCKPOINTER)RTMemAlloc(sizeof(VDIIMAGEBLOCKPOINTER) * getImageBlocks(&Hdr)); 3227 if (!paBlocks) 3228 { 3229 rc = vdIfError(pIfError, VERR_NO_MEMORY, RT_SRC_POS, 3230 "Failed to allocate memory for block array"); 3231 break; 3232 } 3233 3234 /* Read blocks array. */ 3235 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, offStartBlocks, paBlocks, 3236 getImageBlocks(&Hdr) * sizeof(VDIIMAGEBLOCKPOINTER), 3237 NULL); 3238 if (RT_FAILURE(rc)) 3239 { 3240 rc = vdIfError(pIfError, VERR_VD_IMAGE_REPAIR_IMPOSSIBLE, RT_SRC_POS, 3241 "Failed to read block array (at %llu), %Rrc", 3242 offStartBlocks, rc); 3243 break; 3244 } 3245 3246 pu32BlockBitmap = (uint32_t *)RTMemAllocZ(RT_ALIGN_Z(getImageBlocks(&Hdr) / 8, 4)); 3247 if (!pu32BlockBitmap) 3248 { 3249 rc = vdIfError(pIfError, VERR_NO_MEMORY, RT_SRC_POS, 3250 "Failed to allocate memory for block bitmap"); 3251 break; 3252 } 3253 3254 for (uint32_t i = 0; i < getImageBlocks(&Hdr); i++) 3255 { 3256 if (IS_VDI_IMAGE_BLOCK_ALLOCATED(paBlocks[i])) 3257 { 3258 uint64_t offBlock = (uint64_t)paBlocks[i] * cbTotalBlockData 3259 + offStartData; 3260 3261 /* 3262 * Check that the offsets are valid (inside of the image) and 3263 * that there are no double references. 3264 */ 3265 if (offBlock + cbTotalBlockData > cbFile) 3266 { 3267 vdIfErrorMessage(pIfError, "Entry %u points to invalid offset %llu, clearing\n", 3268 i, offBlock); 3269 paBlocks[i] = VDI_IMAGE_BLOCK_FREE; 3270 fRepairBlockArray = true; 3271 } 3272 else if (ASMBitTestAndSet(pu32BlockBitmap, paBlocks[i])) 3273 { 3274 vdIfErrorMessage(pIfError, "Entry %u points to an already referenced data block, clearing\n", 3275 i); 3276 paBlocks[i] = VDI_IMAGE_BLOCK_FREE; 3277 fRepairBlockArray = true; 3278 } 3279 } 3280 } 3281 3282 /* Write repaired structures now. */ 3283 if (!fRepairBlockArray) 3284 vdIfErrorMessage(pIfError, "VDI image is in a consistent state, no repair required\n"); 3285 else if (!(fFlags & VD_REPAIR_DRY_RUN)) 3286 { 3287 for (uint32_t i = 0; i < getImageBlocks(&Hdr); i++) 3288 paBlocks[i] = RT_H2BE_U32(paBlocks[i]); 3289 3290 vdIfErrorMessage(pIfError, "Writing repaired block allocation table...\n"); 3291 3292 rc = vdIfIoIntFileWriteSync(pIfIo, pStorage, offStartBlocks, paBlocks, 3293 getImageBlocks(&Hdr) * sizeof(VDIIMAGEBLOCKPOINTER), 3294 NULL); 3295 if (RT_FAILURE(rc)) 3296 { 3297 rc = vdIfError(pIfError, VERR_VD_IMAGE_REPAIR_IMPOSSIBLE, RT_SRC_POS, 3298 "Could not write repaired block allocation table (at %llu), %Rrc", 3299 offStartBlocks, rc); 3300 break; 3301 } 3302 } 3303 3304 vdIfErrorMessage(pIfError, "Corrupted VDI image repaired successfully\n"); 3305 } while(0); 3306 3307 if (paBlocks) 3308 RTMemFree(paBlocks); 3309 3310 if (pu32BlockBitmap) 3311 RTMemFree(pu32BlockBitmap); 3312 3313 if (pStorage) 3314 vdIfIoIntFileClose(pIfIo, pStorage); 3104 3315 3105 3316 LogFlowFunc(("returns %Rrc\n", rc)); … … 3209 3420 vdiAsyncDiscard, 3210 3421 /* pfnRepair */ 3211 NULL3422 vdiRepair 3212 3423 }; -
trunk/src/VBox/Storage/VHD.cpp
r40107 r40240 3274 3274 vdIfErrorMessage(pIfError, "Entry %u points to invalid offset %llu, clearing\n", 3275 3275 i, offBlock); 3276 paBat[i] = 0;3276 paBat[i] = UINT32_C(0xffffffff); 3277 3277 fRepairBat = true; 3278 3278 } … … 3285 3285 } 3286 3286 3287 if (ASMBitTestAndSet(pu32BlockBitmap, (paBat[i] - idxMinBlock) / (cbBlock / VHD_SECTOR_SIZE))) 3287 if ( paBat[i] != UINT32_C(0xffffffff) 3288 && ASMBitTestAndSet(pu32BlockBitmap, (paBat[i] - idxMinBlock) / (cbBlock / VHD_SECTOR_SIZE))) 3288 3289 { 3289 3290 vdIfErrorMessage(pIfError, "Entry %u points to an already referenced data block, clearing\n", 3290 3291 i); 3291 paBat[i] = 0;3292 paBat[i] = UINT32_C(0xffffffff); 3292 3293 fRepairBat = true; 3293 3294 } -
trunk/src/VBox/Storage/testcase/vbox-img.cpp
r38945 r40240 60 60 " --size <size in bytes>\n" 61 61 " [--format VDI|VMDK|VHD] (default: VDI)\n" 62 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n", 62 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n" 63 "\n" 64 " repair --filename <filename>\n" 65 " [--dry-run]\n" 66 " [--format VDI|VMDK|VHD] (default: autodetect)\n", 63 67 g_pszProgName); 64 68 } … … 1158 1162 1159 1163 1164 int handleRepair(HandlerArg *a) 1165 { 1166 int rc = VINF_SUCCESS; 1167 PVBOXHDD pDisk = NULL; 1168 const char *pszFilename = NULL; 1169 char *pszBackend = NULL; 1170 const char *pszFormat = NULL; 1171 bool fDryRun = false; 1172 VDTYPE enmType = VDTYPE_HDD; 1173 1174 /* Parse the command line. */ 1175 static const RTGETOPTDEF s_aOptions[] = 1176 { 1177 { "--filename", 'f', RTGETOPT_REQ_STRING }, 1178 { "--dry-run", 'd', RTGETOPT_REQ_NOTHING }, 1179 { "--format", 'b', RTGETOPT_REQ_STRING } 1180 }; 1181 int ch; 1182 RTGETOPTUNION ValueUnion; 1183 RTGETOPTSTATE GetState; 1184 RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0 /* fFlags */); 1185 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 1186 { 1187 switch (ch) 1188 { 1189 case 'f': // --filename 1190 pszFilename = ValueUnion.psz; 1191 break; 1192 1193 case 'd': // --dry-run 1194 fDryRun = true; 1195 break; 1196 1197 case 'b': // --format 1198 pszFormat = ValueUnion.psz; 1199 break; 1200 1201 default: 1202 ch = RTGetOptPrintError(ch, &ValueUnion); 1203 printUsage(g_pStdErr); 1204 return ch; 1205 } 1206 } 1207 1208 /* Check for mandatory parameters. */ 1209 if (!pszFilename) 1210 return errorSyntax("Mandatory --filename option missing\n"); 1211 1212 /* just try it */ 1213 if (!pszFormat) 1214 { 1215 rc = VDGetFormat(NULL, NULL, pszFilename, &pszBackend, &enmType); 1216 if (RT_FAILURE(rc)) 1217 return errorSyntax("Format autodetect failed: %Rrc\n", rc); 1218 pszFormat = pszBackend; 1219 } 1220 1221 rc = VDRepair(pVDIfs, NULL, pszFilename, pszFormat, fDryRun ? VD_REPAIR_DRY_RUN : 0); 1222 if (RT_FAILURE(rc)) 1223 rc = errorRuntime("Error while repairing the virtual disk: %Rrc\n", rc); 1224 1225 if (pszBackend) 1226 RTStrFree(pszBackend); 1227 return rc; 1228 } 1229 1230 1160 1231 int main(int argc, char *argv[]) 1161 1232 { … … 1246 1317 { "createcache", handleCreateCache }, 1247 1318 { "createbase", handleCreateBase }, 1319 { "repair", handleRepair }, 1248 1320 { NULL, NULL } 1249 1321 };
Note:
See TracChangeset
for help on using the changeset viewer.