Changeset 69609 in vbox for trunk/src/VBox/Runtime/common/dvm/dvm.cpp
- Timestamp:
- Nov 7, 2017 6:59:38 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dvm/dvm.cpp
r69111 r69609 101 101 * Supported volume formats. 102 102 */ 103 static PCRTDVMFMTOPS g_aDvmFmts[] =103 static PCRTDVMFMTOPS const g_aDvmFmts[] = 104 104 { 105 105 &g_rtDvmFmtMbr, … … 113 113 * This is indexed by RTDVMVOLTYPE. 114 114 */ 115 static const char * g_apcszDvmVolTypes[] =115 static const char * const g_apszDvmVolTypes[] = 116 116 { 117 117 "Invalid", … … 130 130 "Solaris" 131 131 }; 132 AssertCompile(RT_ELEMENTS(g_apszDvmVolTypes) == RTDVMVOLTYPE_END); 133 132 134 133 135 /** … … 139 141 * @param phVol Where to store the generic volume handle on success. 140 142 */ 141 static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, 142 PRTDVMVOLUME phVol) 143 { 144 int rc = VINF_SUCCESS; 145 PRTDVMVOLUMEINTERNAL pVol = NULL; 146 147 pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL)); 143 static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUME phVol) 144 { 145 PRTDVMVOLUMEINTERNAL pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL)); 148 146 if (pVol) 149 147 { … … 154 152 155 153 *phVol = pVol; 156 } 157 else 158 rc = VERR_NO_MEMORY; 159 160 return rc; 154 return VINF_SUCCESS; 155 } 156 return VERR_NO_MEMORY; 161 157 } 162 158 … … 184 180 } 185 181 186 RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, PFNDVMREAD pfnRead, 187 PFNDVMWRITE pfnWrite, uint64_t cbDisk, 188 uint64_t cbSector, uint32_t fFlags, void *pvUser) 189 { 190 int rc = VINF_SUCCESS;191 PRTDVMINTERNAL pThis;192 193 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_MASK),194 ("Invalid flags given %#x\n", fFlags),195 VERR_INVALID_PARAMETER);196 197 pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));198 if (pThis)199 {200 pThis->u32Magic = RTDVM_MAGIC;201 pThis->DvmDisk.cbDisk = cbDisk;202 pThis->DvmDisk.cbSector = cbSector;203 pThis->DvmDisk.pvUser = pvUser;204 pThis->DvmDisk.pfnRead = pfnRead; 205 pThis->DvmDisk.pfnWrite = pfnWrite;206 pThis->pDvmFmtOps = NULL;207 pThis->hVolMgrFmt = NIL_RTDVMFMT;208 pThis->fFlags = fFlags;209 pThis->cRefs = 1;210 RTListInit(&pThis->VolumeList); 211 *phVolMgr = pThis;212 }213 else182 183 RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, RTVFSFILE hVfsFile, uint32_t cbSector, uint32_t fFlags) 184 { 185 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_VALID_MASK), ("Invalid flags given %#x\n", fFlags), VERR_INVALID_FLAGS); 186 uint32_t cRefs = RTVfsFileRetain(hVfsFile); 187 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE); 188 189 uint64_t cbDisk; 190 int rc = RTVfsFileGetSize(hVfsFile, &cbDisk); 191 if (RT_SUCCESS(rc)) 192 { 193 PRTDVMINTERNAL pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL)); 194 if (pThis) 195 { 196 pThis->u32Magic = RTDVM_MAGIC; 197 pThis->DvmDisk.cbDisk = cbDisk; 198 pThis->DvmDisk.cbSector = cbSector; 199 pThis->DvmDisk.hVfsFile = hVfsFile; 200 201 pThis->pDvmFmtOps = NULL; 202 pThis->hVolMgrFmt = NIL_RTDVMFMT; 203 pThis->fFlags = fFlags; 204 pThis->cRefs = 1; 205 RTListInit(&pThis->VolumeList); 206 207 *phVolMgr = pThis; 208 return VINF_SUCCESS; 209 } 214 210 rc = VERR_NO_MEMORY; 215 211 } 212 RTVfsFileRelease(hVfsFile); 216 213 return rc; 217 214 } 215 218 216 219 217 RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr) … … 235 233 static void rtDvmDestroy(PRTDVMINTERNAL pThis) 236 234 { 235 pThis->u32Magic = RTDVM_MAGIC_DEAD; 236 237 237 if (pThis->hVolMgrFmt != NIL_RTDVMFMT) 238 238 { … … 242 242 pThis->pDvmFmtOps->pfnClose(pThis->hVolMgrFmt); 243 243 pThis->hVolMgrFmt = NIL_RTDVMFMT; 244 } 245 246 pThis->DvmDisk.cbDisk = 0; 247 pThis->DvmDisk.pvUser = NULL; 248 pThis->DvmDisk.pfnRead = NULL; 249 pThis->DvmDisk.pfnWrite = NULL; 250 pThis->u32Magic = RTDVM_MAGIC_DEAD; 244 pThis->pDvmFmtOps = NULL; 245 } 246 247 pThis->DvmDisk.cbDisk = 0; 248 pThis->DvmDisk.cbSector = 0; 249 if (pThis->DvmDisk.hVfsFile != NIL_RTVFSFILE) 250 { 251 RTVfsFileRelease(pThis->DvmDisk.hVfsFile); 252 pThis->DvmDisk.hVfsFile = NIL_RTVFSFILE; 253 } 251 254 RTMemFree(pThis); 252 255 } … … 269 272 RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr) 270 273 { 271 int rc = VINF_SUCCESS; 272 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED; 274 PRTDVMINTERNAL pThis = hVolMgr; 275 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 276 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE); 277 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER); 278 279 Assert(!pThis->pDvmFmtOps); 280 281 /* 282 * Let each format backend have a go at the disk, pick the one which scores the highest. 283 */ 284 int rc = VINF_SUCCESS; 285 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED; 273 286 PCRTDVMFMTOPS pDvmFmtOpsMatch = NULL; 274 PRTDVMINTERNAL pThis = hVolMgr;275 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);276 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);277 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);278 279 Assert(!pThis->pDvmFmtOps);280 281 287 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++) 282 288 { 283 uint32_t uScore ;289 uint32_t uScore = 0; 284 290 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i]; 285 291 286 292 rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore); 287 if ( RT_SUCCESS(rc) 288 && uScore > uScoreMax) 293 if (RT_SUCCESS(rc)) 289 294 { 290 pDvmFmtOpsMatch = pDvmFmtOps; 291 uScoreMax = uScore; 292 } 293 else if (RT_FAILURE(rc)) 294 break; 295 } 296 297 if (RT_SUCCESS(rc)) 298 { 299 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED) 300 { 301 AssertPtr(pDvmFmtOpsMatch); 302 303 /* Open the format. */ 304 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt); 305 if (RT_SUCCESS(rc)) 295 if (uScore > uScoreMax) 306 296 { 307 uint32_t cVols; 308 309 pThis->pDvmFmtOps = pDvmFmtOpsMatch; 310 311 cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt); 312 313 /* Construct volume list. */ 314 if (cVols) 315 { 316 PRTDVMVOLUMEINTERNAL pVol = NULL; 317 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT; 318 319 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt); 320 if (RT_SUCCESS(rc)) 321 { 322 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 323 if (RT_FAILURE(rc)) 324 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 325 } 326 327 if (RT_SUCCESS(rc)) 328 { 329 cVols--; 330 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 331 332 while ( cVols > 0 333 && RT_SUCCESS(rc)) 334 { 335 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt); 336 if (RT_SUCCESS(rc)) 337 { 338 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 339 if (RT_FAILURE(rc)) 340 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 341 else 342 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 343 cVols--; 344 } 345 } 346 } 347 348 if (RT_FAILURE(rc)) 349 { 350 /* Remove all entries. */ 351 PRTDVMVOLUMEINTERNAL pItNext, pIt; 352 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode) 353 { 354 RTListNodeRemove(&pIt->VolumeNode); 355 rtDvmVolumeDestroy(pIt); 356 } 357 } 358 } 297 pDvmFmtOpsMatch = pDvmFmtOps; 298 uScoreMax = uScore; 359 299 } 360 300 } 361 301 else 362 rc = VERR_NOT_SUPPORTED; 363 } 364 302 return rc; 303 } 304 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED) 305 { 306 AssertPtr(pDvmFmtOpsMatch); 307 308 /* 309 * Open the format. 310 */ 311 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt); 312 if (RT_SUCCESS(rc)) 313 { 314 pThis->pDvmFmtOps = pDvmFmtOpsMatch; 315 316 /* 317 * Construct volume list (we're done if none). 318 */ 319 uint32_t cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt); 320 if (cVols == 0) 321 return VINF_SUCCESS; 322 323 /* First volume. */ 324 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT; 325 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt); 326 if (RT_SUCCESS(rc)) 327 { 328 for (;;) 329 { 330 PRTDVMVOLUMEINTERNAL pVol = NULL; 331 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 332 if (RT_FAILURE(rc)) 333 { 334 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 335 break; 336 } 337 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 338 339 /* Done?*/ 340 cVols--; 341 if (cVols < 1) 342 return VINF_SUCCESS; 343 344 /* Next volume. */ 345 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt); 346 if (RT_FAILURE(rc)) 347 break; 348 } 349 350 /* Bail out. */ 351 PRTDVMVOLUMEINTERNAL pItNext, pIt; 352 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode) 353 { 354 RTListNodeRemove(&pIt->VolumeNode); 355 rtDvmVolumeDestroy(pIt); 356 } 357 } 358 359 /** @todo shouldn't we close the format too here? */ 360 } 361 } 362 else 363 rc = VERR_NOT_SUPPORTED; 365 364 return rc; 366 365 } … … 368 367 RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt) 369 368 { 370 int rc = VERR_NOT_SUPPORTED;371 369 PRTDVMINTERNAL pThis = hVolMgr; 372 370 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 373 371 AssertPtrReturn(pszFmt, VERR_INVALID_POINTER); 374 372 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE); 375 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_ INVALID_HANDLE);373 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER); 376 374 377 375 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++) 378 376 { 379 377 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i]; 380 381 378 if (!RTStrCmp(pDvmFmtOps->pcszFmt, pszFmt)) 382 379 { 383 rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);380 int rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt); 384 381 if (RT_SUCCESS(rc)) 385 382 pThis->pDvmFmtOps = pDvmFmtOps; 386 387 break; 383 return rc; 388 384 } 389 385 } 390 391 return rc; 386 return VERR_NOT_SUPPORTED; 392 387 } 393 388 … … 444 439 RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext) 445 440 { 446 int rc = VERR_DVM_MAP_NO_VOLUME;447 441 PRTDVMINTERNAL pThis = hVolMgr; 448 442 PRTDVMVOLUMEINTERNAL pVol = hVol; … … 454 448 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER); 455 449 456 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol,457 450 int rc = VERR_DVM_MAP_NO_VOLUME; 451 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode); 458 452 if (pVolNext) 459 453 { … … 466 460 } 467 461 468 RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, 469 bool *pfAllocated) 470 { 471 int rc = VINF_SUCCESS; 472 PRTDVMINTERNAL pThis = hVolMgr; 462 RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, bool *pfAllocated) 463 { 464 PRTDVMINTERNAL pThis = hVolMgr; 473 465 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 474 466 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER); 475 467 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE); 476 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE); 477 AssertReturn(off + cb <= pThis->DvmDisk.cbDisk * pThis->DvmDisk.cbSector, 478 VERR_INVALID_PARAMETER); 468 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_WRONG_ORDER); 469 AssertMsgReturn( off <= pThis->DvmDisk.cbDisk 470 || cb <= pThis->DvmDisk.cbDisk 471 || off + cb <= pThis->DvmDisk.cbDisk, 472 ("off=%#RX64 cb=%#RX64 cbDisk=%#RX64\n", off, cb, pThis->DvmDisk.cbDisk), 473 VERR_OUT_OF_RANGE); 479 474 480 475 /* Check whether the range is inuse by the volume manager metadata first. */ 481 rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);476 int rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated); 482 477 if (RT_FAILURE(rc)) 483 478 return rc; … … 513 508 { 514 509 bool fVolAllocated = true; 515 516 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, 517 &fVolAllocated); 510 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, &fVolAllocated); 518 511 if (RT_FAILURE(rc)) 519 512 break; 520 elseif (fVolAllocated)513 if (fVolAllocated) 521 514 { 522 515 fAllocated = true; … … 657 650 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_END, NULL); 658 651 659 return g_apcszDvmVolTypes[enmVolType]; 660 } 652 return g_apszDvmVolTypes[enmVolType]; 653 } 654
Note:
See TracChangeset
for help on using the changeset viewer.