Changeset 40027 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Feb 7, 2012 11:09:31 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 76150
- Location:
- trunk/src/VBox/Runtime/common/dvm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dvm/dvm.cpp
r37270 r40027 36 36 #include <iprt/asm.h> 37 37 #include <iprt/string.h> 38 #include <iprt/list.h> 38 39 #include "internal/dvm.h" 39 40 … … 55 56 /** The format specific volume manager data. */ 56 57 RTDVMFMT hVolMgrFmt; 58 /** Flags passed on manager creation. */ 59 uint32_t fFlags; 57 60 /** Reference counter. */ 58 61 uint32_t volatile cRefs; 62 /** List of recognised volumes (RTDVMVOLUMEINTERNAL). */ 63 RTLISTANCHOR VolumeList; 59 64 } RTDVMINTERNAL; 60 65 /** Pointer to an internal volume manager. */ … … 67 72 { 68 73 /** The DVM volume magic (RTDVMVOLUME_MAGIC). */ 69 uint32_t u32Magic; 74 uint32_t u32Magic; 75 /** Node for the volume list. */ 76 RTLISTNODE VolumeNode; 70 77 /** Pointer to the owning volume manager. */ 71 PRTDVMINTERNAL pVolMgr;78 PRTDVMINTERNAL pVolMgr; 72 79 /** Format specific volume data. */ 73 RTDVMVOLUMEFMT hVolFmt; 80 RTDVMVOLUMEFMT hVolFmt; 81 /** Set block status.callback */ 82 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus; 83 /** Opaque user data. */ 84 void *pvUser; 74 85 /** Reference counter. */ 75 uint32_t volatile cRefs;86 uint32_t volatile cRefs; 76 87 } RTDVMVOLUMEINTERNAL; 77 88 /** Pointer to an internal volume. */ … … 118 129 }; 119 130 131 /** 132 * Creates a new volume. 133 * 134 * @returns IPRT status code. 135 * @param pThis The DVM map instance. 136 * @param hVolFmt The format specific volume handle. 137 * @param phVol Where to store the generic volume handle on success. 138 */ 139 static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, 140 PRTDVMVOLUME phVol) 141 { 142 int rc = VINF_SUCCESS; 143 PRTDVMVOLUMEINTERNAL pVol = NULL; 144 145 pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL)); 146 if (VALID_PTR(pVol)) 147 { 148 pVol->u32Magic = RTDVMVOLUME_MAGIC; 149 pVol->cRefs = 0; 150 pVol->pVolMgr = pThis; 151 pVol->hVolFmt = hVolFmt; 152 153 *phVol = pVol; 154 } 155 else 156 rc = VERR_NO_MEMORY; 157 158 return rc; 159 } 160 161 /** 162 * Destroys a volume handle. 163 * 164 * @param pThis The volume to destroy. 165 */ 166 static void rtDvmVolumeDestroy(PRTDVMVOLUMEINTERNAL pThis) 167 { 168 PRTDVMINTERNAL pVolMgr = pThis->pVolMgr; 169 170 AssertPtr(pVolMgr); 171 172 /* Close the volume. */ 173 pVolMgr->pDvmFmtOps->pfnVolumeClose(pThis->hVolFmt); 174 175 pThis->u32Magic = RTDVMVOLUME_MAGIC_DEAD; 176 pThis->pVolMgr = NULL; 177 pThis->hVolFmt = NIL_RTDVMVOLUMEFMT; 178 RTMemFree(pThis); 179 180 /* Release the reference of the volume manager. */ 181 RTDvmRelease(pVolMgr); 182 } 183 120 184 RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, PFNDVMREAD pfnRead, 121 185 PFNDVMWRITE pfnWrite, uint64_t cbDisk, 122 uint64_t cbSector, void *pvUser)186 uint64_t cbSector, uint32_t fFlags, void *pvUser) 123 187 { 124 188 int rc = VINF_SUCCESS; 125 189 PRTDVMINTERNAL pThis; 190 191 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_MASK), 192 ("Invalid flags given %#x\n", fFlags), 193 VERR_INVALID_PARAMETER); 126 194 127 195 pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL)); … … 136 204 pThis->pDvmFmtOps = NULL; 137 205 pThis->hVolMgrFmt = NIL_RTDVMFMT; 206 pThis->fFlags = fFlags; 138 207 pThis->cRefs = 1; 208 RTListInit(&pThis->VolumeList); 139 209 *phVolMgr = pThis; 140 210 } … … 232 302 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt); 233 303 if (RT_SUCCESS(rc)) 304 { 305 uint32_t cVols; 306 234 307 pThis->pDvmFmtOps = pDvmFmtOpsMatch; 308 309 cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt); 310 311 /* Construct volume list. */ 312 if (cVols) 313 { 314 PRTDVMVOLUMEINTERNAL pVol = NULL; 315 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT; 316 317 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt); 318 if (RT_SUCCESS(rc)) 319 { 320 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 321 if (RT_FAILURE(rc)) 322 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 323 } 324 325 if (RT_SUCCESS(rc)) 326 { 327 cVols--; 328 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 329 330 while ( cVols > 0 331 && RT_SUCCESS(rc)) 332 { 333 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt); 334 if (RT_SUCCESS(rc)) 335 { 336 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 337 if (RT_FAILURE(rc)) 338 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 339 else 340 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 341 cVols--; 342 } 343 } 344 } 345 346 if (RT_FAILURE(rc)) 347 { 348 PRTDVMVOLUMEINTERNAL pItNext, pIt; 349 350 /* Remove all entries. */ 351 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode) 352 { 353 RTListNodeRemove(&pIt->VolumeNode); 354 rtDvmVolumeDestroy(pIt); 355 } 356 } 357 } 358 } 235 359 } 236 360 else … … 243 367 RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt) 244 368 { 245 int rc = V INF_SUCCESS;369 int rc = VERR_NOT_SUPPORTED; 246 370 PRTDVMINTERNAL pThis = hVolMgr; 247 371 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); … … 297 421 } 298 422 299 static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt,300 PRTDVMVOLUME phVol)301 {302 int rc = VINF_SUCCESS;303 PRTDVMVOLUMEINTERNAL pVol = NULL;304 305 pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL));306 if (VALID_PTR(pVol))307 {308 pVol->u32Magic = RTDVMVOLUME_MAGIC;309 pVol->cRefs = 1;310 pVol->pVolMgr = pThis;311 pVol->hVolFmt = hVolFmt;312 313 /* Reference the volume manager. */314 RTDvmRetain(pThis);315 *phVol = pVol;316 }317 else318 rc = VERR_NO_MEMORY;319 320 return rc;321 }322 323 423 RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol) 324 424 { 325 int rc = V INF_SUCCESS;425 int rc = VERR_DVM_MAP_EMPTY; 326 426 PRTDVMINTERNAL pThis = hVolMgr; 327 427 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); … … 330 430 AssertPtrReturn(phVol, VERR_INVALID_POINTER); 331 431 332 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT; 333 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt); 334 if (RT_SUCCESS(rc)) 335 { 336 rc = rtDvmVolumeCreate(pThis, hVolFmt, phVol); 337 if (RT_FAILURE(rc)) 338 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 432 PRTDVMVOLUMEINTERNAL pVol = RTListGetFirst(&pThis->VolumeList, RTDVMVOLUMEINTERNAL, VolumeNode); 433 if (pVol) 434 { 435 rc = VINF_SUCCESS; 436 RTDvmVolumeRetain(pVol); 437 *phVol = pVol; 339 438 } 340 439 … … 344 443 RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext) 345 444 { 346 int rc = V INF_SUCCESS;445 int rc = VERR_DVM_MAP_NO_VOLUME; 347 446 PRTDVMINTERNAL pThis = hVolMgr; 348 447 PRTDVMVOLUMEINTERNAL pVol = hVol; … … 354 453 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER); 355 454 356 RTDVMVOLUMEFMT hVolFmtNext = NIL_RTDVMVOLUMEFMT; 357 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmtNext); 358 if (RT_SUCCESS(rc)) 359 { 360 rc = rtDvmVolumeCreate(pThis, hVolFmtNext, phVolNext); 361 if (RT_FAILURE(rc)) 362 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmtNext); 363 } 455 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol, 456 RTDVMVOLUMEINTERNAL, VolumeNode); 457 if (pVolNext) 458 { 459 rc = VINF_SUCCESS; 460 RTDvmVolumeRetain(pVolNext); 461 *phVolNext = pVolNext; 462 } 463 464 return rc; 465 } 466 467 RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, 468 bool *pfAllocated) 469 { 470 int rc = VINF_SUCCESS; 471 bool fAllocated = false; 472 PRTDVMINTERNAL pThis = hVolMgr; 473 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 474 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER); 475 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); 479 480 while ( cb > 0 481 && !fAllocated) 482 { 483 PRTDVMVOLUMEINTERNAL pVol; 484 bool fVolFound = false; 485 size_t cbIntersect; 486 uint64_t offVol; 487 488 /* 489 * Search through all volumes. It is not possible to 490 * get all start sectors and sizes of all volumes here 491 * because volumes can be scattered around the disk for certain formats. 492 * Linux LVM is one example, extents of logical volumes don't need to be 493 * contigous on the medium. 494 */ 495 RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode) 496 { 497 bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off, 498 cb, &offVol, 499 &cbIntersect); 500 if (fIntersect) 501 { 502 fVolFound = true; 503 if (pVol->pfnQueryBlockStatus) 504 { 505 bool fVolAllocated = true; 506 507 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, 508 &fVolAllocated); 509 if (RT_FAILURE(rc)) 510 break; 511 } 512 else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED)) 513 fAllocated = true; 514 /* else, flag is set, continue. */ 515 516 cb -= cbIntersect; 517 off += cbIntersect; 518 break; 519 } 520 } 521 522 if (!fVolFound) 523 { 524 if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED) 525 fAllocated = true; 526 527 cb -= pThis->DvmDisk.cbSector; 528 off += pThis->DvmDisk.cbSector; 529 } 530 } 531 532 *pfAllocated = fAllocated; 364 533 365 534 return rc; … … 373 542 374 543 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 375 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis)); 544 AssertMsg(cRefs >= 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis)); 545 if (cRefs == 1) 546 RTDvmRetain(pThis->pVolMgr); 376 547 return cRefs; 377 }378 379 /**380 * Destroys a volume handle.381 *382 * @param pThis The volume to destroy.383 */384 static void rtDvmVolumeDestroy(PRTDVMVOLUMEINTERNAL pThis)385 {386 PRTDVMINTERNAL pVolMgr = pThis->pVolMgr;387 388 AssertPtr(pVolMgr);389 390 /* Close the volume. */391 pVolMgr->pDvmFmtOps->pfnVolumeClose(pThis->hVolFmt);392 393 pThis->u32Magic = RTDVMVOLUME_MAGIC_DEAD;394 pThis->pVolMgr = NULL;395 pThis->hVolFmt = NIL_RTDVMVOLUMEFMT;396 RTMemFree(pThis);397 398 /* Release the reference of the volume manager. */399 RTDvmRelease(pVolMgr);400 548 } 401 549 … … 411 559 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis)); 412 560 if (cRefs == 0) 413 rtDvmVolumeDestroy(pThis); 561 { 562 /* Release the volume manager. */ 563 pThis->pfnQueryBlockStatus = NULL; 564 RTDvmRelease(pThis->pVolMgr); 565 } 414 566 return cRefs; 567 } 568 569 RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol, 570 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus, 571 void *pvUser) 572 { 573 PRTDVMVOLUMEINTERNAL pThis = hVol; 574 AssertPtrReturnVoid(pThis); 575 AssertReturnVoid(pThis->u32Magic == RTDVMVOLUME_MAGIC); 576 577 pThis->pfnQueryBlockStatus = pfnQueryBlockStatus; 578 pThis->pvUser = pvUser; 415 579 } 416 580 -
trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp
r39083 r40027 466 466 } 467 467 468 DECLCALLBACK(bool) rtDvmFmtBsdLblVolumeIsRangeIntersecting(RTDVMVOLUMEFMT hVolFmt, 469 uint64_t offStart, size_t cbRange, 470 uint64_t *poffVol, 471 size_t *pcbIntersect) 472 { 473 bool fIntersect = false; 474 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 475 476 if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart)) 477 { 478 fIntersect = true; 479 *poffVol = offStart - pVol->offStart; 480 *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart); 481 } 482 483 return fIntersect; 484 } 485 468 486 DECLCALLBACK(int) rtDvmFmtBsdLblVolumeRead(RTDVMVOLUMEFMT hVolFmt, uint64_t off, void *pvBuf, size_t cbRead) 469 487 { … … 512 530 /* pfnVolumeGetFlags */ 513 531 rtDvmFmtBsdLblVolumeGetFlags, 532 /* pfnVolumeIsRangeIntersecting */ 533 rtDvmFmtBsdLblVolumeIsRangeIntersecting, 514 534 /* pfnVolumeRead */ 515 535 rtDvmFmtBsdLblVolumeRead, -
trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp
r39083 r40027 482 482 NOREF(hVolFmt); /* No supported flags for now. */ 483 483 return 0; 484 } 485 486 DECLCALLBACK(bool) rtDvmFmtGptVolumeIsRangeIntersecting(RTDVMVOLUMEFMT hVolFmt, 487 uint64_t offStart, size_t cbRange, 488 uint64_t *poffVol, 489 size_t *pcbIntersect) 490 { 491 bool fIntersect = false; 492 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 493 494 if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart)) 495 { 496 fIntersect = true; 497 *poffVol = offStart - pVol->offStart; 498 *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart); 499 } 500 501 return fIntersect; 484 502 } 485 503 … … 530 548 /* pfnVolumeGetFlags */ 531 549 rtDvmFmtGptVolumeGetFlags, 550 /* pfnVolumeIsRangeIntersecting */ 551 rtDvmFmtGptVolumeIsRangeIntersecting, 532 552 /* pfnVolumeRead */ 533 553 rtDvmFmtGptVolumeRead, -
trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp
r39083 r40027 351 351 352 352 return fFlags; 353 } 354 355 DECLCALLBACK(bool) rtDvmFmtMbrVolumeIsRangeIntersecting(RTDVMVOLUMEFMT hVolFmt, 356 uint64_t offStart, size_t cbRange, 357 uint64_t *poffVol, 358 size_t *pcbIntersect) 359 { 360 bool fIntersect = false; 361 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 362 363 if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart)) 364 { 365 fIntersect = true; 366 *poffVol = offStart - pVol->offStart; 367 *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart); 368 } 369 370 return fIntersect; 353 371 } 354 372 … … 399 417 /* pfnVolumeGetFlags */ 400 418 rtDvmFmtMbrVolumeGetFlags, 419 /* pfnVOlumeIsRangeIntersecting */ 420 rtDvmFmtMbrVolumeIsRangeIntersecting, 401 421 /* pfnVolumeRead */ 402 422 rtDvmFmtMbrVolumeRead,
Note:
See TracChangeset
for help on using the changeset viewer.